@stkxp/cli 0.1.2

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 (371) hide show
  1. package/README.md +273 -0
  2. package/bin/stkxp.mjs +198 -0
  3. package/package.json +97 -0
  4. package/src/bootstrap.mjs +37 -0
  5. package/src/bootstrap.test.mjs +73 -0
  6. package/src/deploy.mjs +145 -0
  7. package/src/deploy.test.mjs +131 -0
  8. package/src/export.mjs +30 -0
  9. package/src/export.test.mjs +56 -0
  10. package/src/secret-input.mjs +64 -0
  11. package/src/secret-input.test.mjs +58 -0
  12. package/src/serve.mjs +83 -0
  13. package/src/serve.test.mjs +93 -0
  14. package/vendor/dist-server/asyncapi/generator.js +1 -0
  15. package/vendor/dist-server/asyncapi/messages.js +1 -0
  16. package/vendor/dist-server/asyncapi/viewer.html +43 -0
  17. package/vendor/dist-server/core/app-config/branding.js +1 -0
  18. package/vendor/dist-server/core/app-config/mantine-theme.js +1 -0
  19. package/vendor/dist-server/core/app-config/mermaid-theme.js +2 -0
  20. package/vendor/dist-server/core/app-config/prompt-optimization.js +1 -0
  21. package/vendor/dist-server/core/app-config/settings.js +1 -0
  22. package/vendor/dist-server/core/config.js +1 -0
  23. package/vendor/dist-server/core/graph/a2a-agent-executor.js +2 -0
  24. package/vendor/dist-server/core/graph/app.js +120 -0
  25. package/vendor/dist-server/core/graph/delegated-agent-adapter.js +1 -0
  26. package/vendor/dist-server/core/graph/graph-builder.js +3 -0
  27. package/vendor/dist-server/core/graph/kibana-agent-executor.js +1 -0
  28. package/vendor/dist-server/core/graph/nodes/context/assistants-context.js +5 -0
  29. package/vendor/dist-server/core/graph/nodes/context/compare-context.js +10 -0
  30. package/vendor/dist-server/core/graph/nodes/context/enrich-context.js +8 -0
  31. package/vendor/dist-server/core/graph/nodes/context/inventory-context.js +4 -0
  32. package/vendor/dist-server/core/graph/nodes/context/namespace-context.js +2 -0
  33. package/vendor/dist-server/core/graph/nodes/context/node-types-context.js +4 -0
  34. package/vendor/dist-server/core/graph/nodes/context/relevant-assistants-context.js +5 -0
  35. package/vendor/dist-server/core/graph/nodes/context/relevant-skills-context.js +5 -0
  36. package/vendor/dist-server/core/graph/nodes/context/skills-context.js +8 -0
  37. package/vendor/dist-server/core/graph/nodes/context/state-setter.js +1 -0
  38. package/vendor/dist-server/core/graph/nodes/control/check-reset.js +1 -0
  39. package/vendor/dist-server/core/graph/nodes/control/topic-detection.js +1 -0
  40. package/vendor/dist-server/core/graph/nodes/governance/human-approval.js +16 -0
  41. package/vendor/dist-server/core/graph/nodes/index.js +1 -0
  42. package/vendor/dist-server/core/graph/nodes/orchestration/suggestion-generator.js +17 -0
  43. package/vendor/dist-server/core/graph/nodes/orchestration/team-decider.js +1 -0
  44. package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/decider-error.js +4 -0
  45. package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/decider-standalone-runner.js +1 -0
  46. package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/decider-synthesis.js +29 -0
  47. package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/pipeline-memory.js +2 -0
  48. package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/pipeline-runner.js +7 -0
  49. package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/team-assistant-utils.js +1 -0
  50. package/vendor/dist-server/core/graph/nodes/orchestration/team-finder.js +13 -0
  51. package/vendor/dist-server/core/graph/nodes/orchestration/team-invoker.js +3 -0
  52. package/vendor/dist-server/core/graph/nodes/orchestration/team-parallel.js +1 -0
  53. package/vendor/dist-server/core/graph/nodes/orchestration/team-pipeline.js +6 -0
  54. package/vendor/dist-server/core/graph/nodes/orchestration/team-router.js +26 -0
  55. package/vendor/dist-server/core/graph/nodes/reasoning/code-executor/index.js +6 -0
  56. package/vendor/dist-server/core/graph/nodes/reasoning/code-executor/resource-bridge.js +2 -0
  57. package/vendor/dist-server/core/graph/nodes/reasoning/code-executor/sandbox.js +6 -0
  58. package/vendor/dist-server/core/graph/nodes/reasoning/code-executor/tool-bridge.js +1 -0
  59. package/vendor/dist-server/core/graph/nodes/reasoning/local-extractor.js +5 -0
  60. package/vendor/dist-server/core/graph/nodes/reasoning/response-generator.js +47 -0
  61. package/vendor/dist-server/core/graph/nodes/reasoning/static-code-executor/index.js +1 -0
  62. package/vendor/dist-server/core/graph/nodes/reasoning/system.js +54 -0
  63. package/vendor/dist-server/core/graph/nodes/reasoning/tool-executor.js +9 -0
  64. package/vendor/dist-server/core/graph/nodes/tools/raw-output.js +4 -0
  65. package/vendor/dist-server/core/graph/nodes/tools/tool-cleaner.js +7 -0
  66. package/vendor/dist-server/core/graph/nodes/tools/tool-execution/execute-tool-calls.js +3 -0
  67. package/vendor/dist-server/core/graph/nodes/tools/tool-execution/invoke.js +1 -0
  68. package/vendor/dist-server/core/graph/nodes/tools/tool-execution/namespace-guard.js +1 -0
  69. package/vendor/dist-server/core/graph/nodes/tools/tool-execution/result-limits.js +3 -0
  70. package/vendor/dist-server/core/graph/nodes/tools/tool-invoker.js +1 -0
  71. package/vendor/dist-server/core/graph/nodes/tools/tool.js +4 -0
  72. package/vendor/dist-server/core/graph/schemas.js +1 -0
  73. package/vendor/dist-server/core/graph/topic-variants.js +1 -0
  74. package/vendor/dist-server/core/graph/types.js +1 -0
  75. package/vendor/dist-server/core/graph/utils/content-utils.js +17 -0
  76. package/vendor/dist-server/core/graph/utils/edge-jsonata-condition.js +1 -0
  77. package/vendor/dist-server/core/graph/utils/engine-vars.js +1 -0
  78. package/vendor/dist-server/core/graph/utils/logging-utils.js +4 -0
  79. package/vendor/dist-server/core/graph/utils/message-utils.js +5 -0
  80. package/vendor/dist-server/core/graph/utils/node-type-defaults-cache.js +1 -0
  81. package/vendor/dist-server/core/graph/utils/sandbox-catalog.js +1 -0
  82. package/vendor/dist-server/core/graph/utils/schema-utils.js +1 -0
  83. package/vendor/dist-server/core/graph/utils/team-context-policy.js +5 -0
  84. package/vendor/dist-server/core/graph/utils/team-node-resolvers.js +1 -0
  85. package/vendor/dist-server/core/graph/utils/tool-result.js +4 -0
  86. package/vendor/dist-server/core/graph/utils/tool-wrapper.js +14 -0
  87. package/vendor/dist-server/core/llm/init-indices.js +1 -0
  88. package/vendor/dist-server/core/llm/models/index.js +1 -0
  89. package/vendor/dist-server/core/llm/models/model.model.js +1 -0
  90. package/vendor/dist-server/core/llm/models/provider.model.js +1 -0
  91. package/vendor/dist-server/core/llm/models/routing-rule.model.js +1 -0
  92. package/vendor/dist-server/core/llm/providers.js +1 -0
  93. package/vendor/dist-server/core/mcp/client.js +1 -0
  94. package/vendor/dist-server/core/runtime/active-runs-registry.js +1 -0
  95. package/vendor/dist-server/core/runtime/system-prompt-cache.js +1 -0
  96. package/vendor/dist-server/core/runtime/trace-bus.js +1 -0
  97. package/vendor/dist-server/core/schema/cluster_health_report.js +1 -0
  98. package/vendor/dist-server/core/schema/cluster_info.js +1 -0
  99. package/vendor/dist-server/core/schema/cluster_license.js +5 -0
  100. package/vendor/dist-server/core/schema/cluster_stats.js +12 -0
  101. package/vendor/dist-server/core/schema/dashboard.js +1 -0
  102. package/vendor/dist-server/core/schema/indices_settings.js +1 -0
  103. package/vendor/dist-server/core/schema/indices_shards.js +1 -0
  104. package/vendor/dist-server/core/schema/indices_stats.js +1 -0
  105. package/vendor/dist-server/core/schema/nodes_info.js +2 -0
  106. package/vendor/dist-server/core/schema/nodes_stats.js +11 -0
  107. package/vendor/dist-server/core/schema/pricing.js +1 -0
  108. package/vendor/dist-server/core/schema/ui.js +1 -0
  109. package/vendor/dist-server/core/schema/zod_client.js +83 -0
  110. package/vendor/dist-server/core/services/a2a-client.js +2 -0
  111. package/vendor/dist-server/core/services/alerts-service.js +1 -0
  112. package/vendor/dist-server/core/services/api-keys-service.js +1 -0
  113. package/vendor/dist-server/core/services/assistant-resolver.js +1 -0
  114. package/vendor/dist-server/core/services/assistants-index-service.js +1 -0
  115. package/vendor/dist-server/core/services/async-conversations-service.js +22 -0
  116. package/vendor/dist-server/core/services/asyncapi-dispatch.js +1 -0
  117. package/vendor/dist-server/core/services/asyncapi-drivers/driver-manager.js +1 -0
  118. package/vendor/dist-server/core/services/asyncapi-drivers/driver-types.js +0 -0
  119. package/vendor/dist-server/core/services/asyncapi-drivers/http-driver.js +1 -0
  120. package/vendor/dist-server/core/services/asyncapi-drivers/nats-driver.js +1 -0
  121. package/vendor/dist-server/core/services/asyncapi-drivers/websocket-driver.js +1 -0
  122. package/vendor/dist-server/core/services/asyncapi-events-service.js +1 -0
  123. package/vendor/dist-server/core/services/asyncapi-reply-service.js +1 -0
  124. package/vendor/dist-server/core/services/asyncapi-sink.js +1 -0
  125. package/vendor/dist-server/core/services/asyncapi-tools-service.js +1 -0
  126. package/vendor/dist-server/core/services/block-repair-service.js +13 -0
  127. package/vendor/dist-server/core/services/chart-renderer.js +1 -0
  128. package/vendor/dist-server/core/services/chat-llms-service.js +1 -0
  129. package/vendor/dist-server/core/services/chat-runs-service.js +1 -0
  130. package/vendor/dist-server/core/services/chat-tools-service.js +1 -0
  131. package/vendor/dist-server/core/services/chat-traces-service.js +1 -0
  132. package/vendor/dist-server/core/services/chats-service.js +5 -0
  133. package/vendor/dist-server/core/services/comparison-service.js +107 -0
  134. package/vendor/dist-server/core/services/default-model.service.js +1 -0
  135. package/vendor/dist-server/core/services/elastic-stack-sync-service.js +2 -0
  136. package/vendor/dist-server/core/services/elasticsearch-wrapper.js +1 -0
  137. package/vendor/dist-server/core/services/embed-rate-limiter.js +1 -0
  138. package/vendor/dist-server/core/services/error-analytics-service.js +1 -0
  139. package/vendor/dist-server/core/services/es-field-resolver.js +1 -0
  140. package/vendor/dist-server/core/services/gateway-platform-types.js +1 -0
  141. package/vendor/dist-server/core/services/gliner-tagging-service.js +1 -0
  142. package/vendor/dist-server/core/services/golden-questions-scoring.js +1 -0
  143. package/vendor/dist-server/core/services/golden-questions-service.js +1 -0
  144. package/vendor/dist-server/core/services/graph-drilldown-service.js +1 -0
  145. package/vendor/dist-server/core/services/graph-registry-service.js +1 -0
  146. package/vendor/dist-server/core/services/hitl-analytics-service.js +1 -0
  147. package/vendor/dist-server/core/services/ingestion-jobs-service.js +1 -0
  148. package/vendor/dist-server/core/services/ingestion-service.js +5 -0
  149. package/vendor/dist-server/core/services/kibana-client-factory.js +1 -0
  150. package/vendor/dist-server/core/services/kibana-client.js +2 -0
  151. package/vendor/dist-server/core/services/kibana-dashboard-extractor.js +1 -0
  152. package/vendor/dist-server/core/services/kibana-service.js +1 -0
  153. package/vendor/dist-server/core/services/llm-analytics-service.js +1 -0
  154. package/vendor/dist-server/core/services/llm-client-resolver.js +1 -0
  155. package/vendor/dist-server/core/services/llm-models-service.js +1 -0
  156. package/vendor/dist-server/core/services/llm-pricing-pure.js +1 -0
  157. package/vendor/dist-server/core/services/llm-pricing-service.js +1 -0
  158. package/vendor/dist-server/core/services/llm-providers-service.js +1 -0
  159. package/vendor/dist-server/core/services/llm-routing-service.js +1 -0
  160. package/vendor/dist-server/core/services/llm-services.js +1 -0
  161. package/vendor/dist-server/core/services/llm-sync-service.js +1 -0
  162. package/vendor/dist-server/core/services/manifest-loader.js +1 -0
  163. package/vendor/dist-server/core/services/mcp-servers-service.js +1 -0
  164. package/vendor/dist-server/core/services/mcp-sync-service.js +1 -0
  165. package/vendor/dist-server/core/services/mcp-tools-service.js +1 -0
  166. package/vendor/dist-server/core/services/memories-service.js +2 -0
  167. package/vendor/dist-server/core/services/memory-analytics-service.js +1 -0
  168. package/vendor/dist-server/core/services/monitoring-analytics-service.js +1 -0
  169. package/vendor/dist-server/core/services/monitoring-service.js +1 -0
  170. package/vendor/dist-server/core/services/multi-kibana-service.js +1 -0
  171. package/vendor/dist-server/core/services/node-latency-service.js +1 -0
  172. package/vendor/dist-server/core/services/package-policy-service.js +2 -0
  173. package/vendor/dist-server/core/services/pdf-service.js +572 -0
  174. package/vendor/dist-server/core/services/plan-service.js +1 -0
  175. package/vendor/dist-server/core/services/platform-direction.js +1 -0
  176. package/vendor/dist-server/core/services/platform-secrets.js +1 -0
  177. package/vendor/dist-server/core/services/platforms-service.js +1 -0
  178. package/vendor/dist-server/core/services/policy-factory.js +1 -0
  179. package/vendor/dist-server/core/services/prompt-cache-service.js +1 -0
  180. package/vendor/dist-server/core/services/provider-rate-limits.js +1 -0
  181. package/vendor/dist-server/core/services/quota-service.js +1 -0
  182. package/vendor/dist-server/core/services/report-assets-service.js +1 -0
  183. package/vendor/dist-server/core/services/run-analytics-collector.js +1 -0
  184. package/vendor/dist-server/core/services/run-stream-sink.js +1 -0
  185. package/vendor/dist-server/core/services/send_mail.js +460 -0
  186. package/vendor/dist-server/core/services/share-service.js +1 -0
  187. package/vendor/dist-server/core/services/slack-signature.js +1 -0
  188. package/vendor/dist-server/core/services/sources-service.js +6 -0
  189. package/vendor/dist-server/core/services/team-mcp-result.js +4 -0
  190. package/vendor/dist-server/core/services/team-mcp-run-tokens.js +1 -0
  191. package/vendor/dist-server/core/services/team-mcp-runner.js +1 -0
  192. package/vendor/dist-server/core/services/team-mcp-server.js +1 -0
  193. package/vendor/dist-server/core/services/team-mcp-tools.js +1 -0
  194. package/vendor/dist-server/core/services/team-mcp-ui.js +551 -0
  195. package/vendor/dist-server/core/services/team-run-progress.js +1 -0
  196. package/vendor/dist-server/core/services/team-runner-headless.js +7 -0
  197. package/vendor/dist-server/core/services/team-search-service.js +1 -0
  198. package/vendor/dist-server/core/services/teams-service.js +1 -0
  199. package/vendor/dist-server/core/services/token-projection-service.js +1 -0
  200. package/vendor/dist-server/core/services/tool-analytics-service.js +1 -0
  201. package/vendor/dist-server/core/services/tool-history-service.js +1 -0
  202. package/vendor/dist-server/core/services/tool-metrics-service.js +1 -0
  203. package/vendor/dist-server/core/services/tool-scoring.js +1 -0
  204. package/vendor/dist-server/core/services/toolbox-import-mappers.js +1 -0
  205. package/vendor/dist-server/core/services/toolbox-import-service.js +1 -0
  206. package/vendor/dist-server/core/services/trigger-service.js +1 -0
  207. package/vendor/dist-server/core/services/version-snapshot-service.js +1 -0
  208. package/vendor/dist-server/core/services/webhook-calls-service.js +1 -0
  209. package/vendor/dist-server/core/tools/compare-chat.js +46 -0
  210. package/vendor/dist-server/core/tools/enrich-chat.js +50 -0
  211. package/vendor/dist-server/core/tools/variable-encoding.js +1 -0
  212. package/vendor/dist-server/core/types/settings.js +1 -0
  213. package/vendor/dist-server/core/utils/ab-evaluator.js +5 -0
  214. package/vendor/dist-server/core/utils/condition-evaluator.js +1 -0
  215. package/vendor/dist-server/core/utils/http-client.js +1 -0
  216. package/vendor/dist-server/core/utils/json-schema-to-form.js +1 -0
  217. package/vendor/dist-server/core/utils/logger.js +3 -0
  218. package/vendor/dist-server/core/utils/owner-scope.js +1 -0
  219. package/vendor/dist-server/core/utils/ownership.js +1 -0
  220. package/vendor/dist-server/core/utils/parallel-tool-executor.js +1 -0
  221. package/vendor/dist-server/core/utils/performance-tracker.js +3 -0
  222. package/vendor/dist-server/core/utils/prompt-optimizer.js +40 -0
  223. package/vendor/dist-server/core/utils/response-cache.js +1 -0
  224. package/vendor/dist-server/core/utils/schema-validator.js +1 -0
  225. package/vendor/dist-server/core/utils/streaming-optimizer.js +2 -0
  226. package/vendor/dist-server/core/utils/string-helpers.js +1 -0
  227. package/vendor/dist-server/core/utils/test-responses.js +9 -0
  228. package/vendor/dist-server/core/utils/text-utils.js +1 -0
  229. package/vendor/dist-server/core/utils/tool-form-trigger.js +1 -0
  230. package/vendor/dist-server/entrypoints/cli-bootstrap-run.js +1 -0
  231. package/vendor/dist-server/entrypoints/cli-deploy-run.js +1 -0
  232. package/vendor/dist-server/entrypoints/cli-deploy.js +1 -0
  233. package/vendor/dist-server/entrypoints/team-runner.js +1 -0
  234. package/vendor/dist-server/generated/toolbox-catalog.js +1 -0
  235. package/vendor/dist-server/index.js +2 -0
  236. package/vendor/dist-server/middleware/integration-logos.js +1 -0
  237. package/vendor/dist-server/middleware/plan-guard.js +1 -0
  238. package/vendor/dist-server/openapi/generator.js +1 -0
  239. package/vendor/dist-server/openapi/html-tool-spec.js +1 -0
  240. package/vendor/dist-server/routes/a2a-routes.js +1 -0
  241. package/vendor/dist-server/routes/a2a-server-routes.js +5 -0
  242. package/vendor/dist-server/routes/admin.js +1 -0
  243. package/vendor/dist-server/routes/assistants-routes.js +1 -0
  244. package/vendor/dist-server/routes/asyncapi-routes.js +1 -0
  245. package/vendor/dist-server/routes/auth.js +1 -0
  246. package/vendor/dist-server/routes/billing-routes.js +1 -0
  247. package/vendor/dist-server/routes/chat-llms.js +1 -0
  248. package/vendor/dist-server/routes/chat-tools.js +1 -0
  249. package/vendor/dist-server/routes/chat-traces.js +1 -0
  250. package/vendor/dist-server/routes/chats.js +1 -0
  251. package/vendor/dist-server/routes/clusters.js +1 -0
  252. package/vendor/dist-server/routes/compare.js +43 -0
  253. package/vendor/dist-server/routes/connectors-routes.js +1 -0
  254. package/vendor/dist-server/routes/consumptions-routes.js +1 -0
  255. package/vendor/dist-server/routes/data-admin-routes.js +1 -0
  256. package/vendor/dist-server/routes/data-transfer-routes.js +1 -0
  257. package/vendor/dist-server/routes/elastic-tool-execution-routes.js +1 -0
  258. package/vendor/dist-server/routes/geo-proxy-routes.js +1 -0
  259. package/vendor/dist-server/routes/golden-questions-routes.js +1 -0
  260. package/vendor/dist-server/routes/graph-registry.js +1 -0
  261. package/vendor/dist-server/routes/graph-templates-routes.js +1 -0
  262. package/vendor/dist-server/routes/helpdesk-routes.js +35 -0
  263. package/vendor/dist-server/routes/html-routes.js +1 -0
  264. package/vendor/dist-server/routes/index.js +1 -0
  265. package/vendor/dist-server/routes/indices.js +1 -0
  266. package/vendor/dist-server/routes/integrations-routes.js +1 -0
  267. package/vendor/dist-server/routes/langgraph.js +7 -0
  268. package/vendor/dist-server/routes/live-resources-routes.js +1 -0
  269. package/vendor/dist-server/routes/llm-analytics.js +1 -0
  270. package/vendor/dist-server/routes/llm-control-plane.js +1 -0
  271. package/vendor/dist-server/routes/llm.js +1 -0
  272. package/vendor/dist-server/routes/mcp-gateway-routes.js +1 -0
  273. package/vendor/dist-server/routes/mcp-query-routes.js +1 -0
  274. package/vendor/dist-server/routes/mcp-servers-routes.js +1 -0
  275. package/vendor/dist-server/routes/mcp-team-routes.js +1 -0
  276. package/vendor/dist-server/routes/mcp-tools-routes.js +1 -0
  277. package/vendor/dist-server/routes/me-routes.js +63 -0
  278. package/vendor/dist-server/routes/memories-routes.js +1 -0
  279. package/vendor/dist-server/routes/monitoring-analytics.js +12 -0
  280. package/vendor/dist-server/routes/monitoring.js +1 -0
  281. package/vendor/dist-server/routes/node-types-routes.js +171 -0
  282. package/vendor/dist-server/routes/nodes.js +1 -0
  283. package/vendor/dist-server/routes/packages.js +1 -0
  284. package/vendor/dist-server/routes/pdf.js +3 -0
  285. package/vendor/dist-server/routes/plan-routes.js +1 -0
  286. package/vendor/dist-server/routes/platform-requests-routes.js +1 -0
  287. package/vendor/dist-server/routes/platforms-routes.js +1 -0
  288. package/vendor/dist-server/routes/prompts-routes.js +1 -0
  289. package/vendor/dist-server/routes/proxy-logos.js +1 -0
  290. package/vendor/dist-server/routes/quality-routes.js +1 -0
  291. package/vendor/dist-server/routes/resources-ingest-routes.js +1 -0
  292. package/vendor/dist-server/routes/resources-routes.js +1 -0
  293. package/vendor/dist-server/routes/schema-routes.js +1 -0
  294. package/vendor/dist-server/routes/settings-original.js +1 -0
  295. package/vendor/dist-server/routes/settings.js +1 -0
  296. package/vendor/dist-server/routes/share-routes.js +1 -0
  297. package/vendor/dist-server/routes/sources-catalog-routes.js +1 -0
  298. package/vendor/dist-server/routes/sources-routes.js +1 -0
  299. package/vendor/dist-server/routes/team-optimizer-routes.js +1 -0
  300. package/vendor/dist-server/routes/team-schedule-routes.js +1 -0
  301. package/vendor/dist-server/routes/teams-routes.js +1 -0
  302. package/vendor/dist-server/routes/tool-analytics.js +1 -0
  303. package/vendor/dist-server/routes/tool-history-routes.js +1 -0
  304. package/vendor/dist-server/routes/tool-metrics-routes.js +1 -0
  305. package/vendor/dist-server/routes/toolbox-import-routes.js +1 -0
  306. package/vendor/dist-server/routes/tools-routes.js +5 -0
  307. package/vendor/dist-server/routes/transcribe-routes.js +1 -0
  308. package/vendor/dist-server/routes/triggers.js +1 -0
  309. package/vendor/dist-server/routes/versions-routes.js +1 -0
  310. package/vendor/dist-server/routes/webhooks-routes.js +1 -0
  311. package/vendor/dist-server/scripts/add-label-to-tools.js +4 -0
  312. package/vendor/dist-server/scripts/migrate-assistants-to-mcp.js +10 -0
  313. package/vendor/dist-server/scripts/migrate-chat-runs.js +8 -0
  314. package/vendor/dist-server/scripts/migrate-mcp-protocol.js +8 -0
  315. package/vendor/dist-server/scripts/migrate-mcp-to-platforms.js +15 -0
  316. package/vendor/dist-server/services/alert-evaluator.js +3 -0
  317. package/vendor/dist-server/services/auth.js +1 -0
  318. package/vendor/dist-server/services/billing-service.js +1 -0
  319. package/vendor/dist-server/services/chat-title-generator.js +12 -0
  320. package/vendor/dist-server/services/clone/clone-executor.js +1 -0
  321. package/vendor/dist-server/services/clone/closure-resolver.js +3 -0
  322. package/vendor/dist-server/services/clone/entity-graph.js +3 -0
  323. package/vendor/dist-server/services/clone/team-bundle-bootstrap.js +1 -0
  324. package/vendor/dist-server/services/clone/team-bundle-crypto.js +1 -0
  325. package/vendor/dist-server/services/clone/team-bundle-encrypted.js +1 -0
  326. package/vendor/dist-server/services/clone/team-bundle.js +1 -0
  327. package/vendor/dist-server/services/cluster-service.js +1 -0
  328. package/vendor/dist-server/services/connection-adapters.js +1 -0
  329. package/vendor/dist-server/services/connectors-service.js +10 -0
  330. package/vendor/dist-server/services/cost-forecast-service.js +1 -0
  331. package/vendor/dist-server/services/eui-ssr-renderer.js +4 -0
  332. package/vendor/dist-server/services/graph-canvas/full-structure-builder.js +1 -0
  333. package/vendor/dist-server/services/graph-templates-service.js +13 -0
  334. package/vendor/dist-server/services/guest-service.js +1 -0
  335. package/vendor/dist-server/services/html-service.js +1 -0
  336. package/vendor/dist-server/services/langgraph-service.js +2 -0
  337. package/vendor/dist-server/services/leaflet-render-service.js +80 -0
  338. package/vendor/dist-server/services/live-resources-service.js +16 -0
  339. package/vendor/dist-server/services/mcp-app-tester-package.js +1 -0
  340. package/vendor/dist-server/services/mcp-gateway/executors/openapi-executor.js +1 -0
  341. package/vendor/dist-server/services/mcp-gateway/gateway-grant-service.js +2 -0
  342. package/vendor/dist-server/services/team-optimizer-service.js +1 -0
  343. package/vendor/dist-server/services/trace-bus-sink.js +1 -0
  344. package/vendor/dist-server/services/user-provisioning-service.js +3 -0
  345. package/vendor/dist-server/templates/mcp-app-tester/src/mcp-http.js +3 -0
  346. package/vendor/dist-server/templates/mcp-app-tester/src/server.js +1 -0
  347. package/vendor/dist-server/utils.js +1 -0
  348. package/vendor/dist-server/ws/assistant-executor.js +7 -0
  349. package/vendor/dist-server/ws/classify-streamed-json-block.js +1 -0
  350. package/vendor/dist-server/ws/collect-response-generator-node-ids.js +1 -0
  351. package/vendor/dist-server/ws/extractors/blockkit-extractor.js +1 -0
  352. package/vendor/dist-server/ws/extractors/echarts-extractor.js +1 -0
  353. package/vendor/dist-server/ws/extractors/eui-extractor.js +1 -0
  354. package/vendor/dist-server/ws/extractors/form-extractor.js +1 -0
  355. package/vendor/dist-server/ws/extractors/index.js +1 -0
  356. package/vendor/dist-server/ws/extractors/leaflet-extractor.js +1 -0
  357. package/vendor/dist-server/ws/extractors/mantine-extractor.js +1 -0
  358. package/vendor/dist-server/ws/extractors/markdown-extractor.js +7 -0
  359. package/vendor/dist-server/ws/extractors/mermaid-extractor.js +1 -0
  360. package/vendor/dist-server/ws/extractors/recharts-extractor.js +1 -0
  361. package/vendor/dist-server/ws/extractors/remotion-extractor.js +1 -0
  362. package/vendor/dist-server/ws/handler.js +66 -0
  363. package/vendor/dist-server/ws/parsers/anthropic-parser.js +7 -0
  364. package/vendor/dist-server/ws/parsers/base-parser.js +3 -0
  365. package/vendor/dist-server/ws/parsers/gemini-parser.js +8 -0
  366. package/vendor/dist-server/ws/parsers/index.js +1 -0
  367. package/vendor/dist-server/ws/parsers/parse-json-blocks.js +1 -0
  368. package/vendor/dist-server/ws/types.js +0 -0
  369. package/vendor/dist-server/ws/utils.js +1 -0
  370. package/vendor/shared/engine-vars.ts +51 -0
  371. package/vendor/shared/llm-providers-config.ts +69 -0
@@ -0,0 +1 @@
1
+ const r=[{slug:"alloydb",sourceType:"alloydb-postgres",title:"AlloyDB PostgreSQL",description:"AlloyDB for PostgreSQL is a fully-managed, PostgreSQL-compatible database for demanding transactional workloads.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"region",type:"string",required:!0,secret:!1,example:"us-central1"},{name:"cluster",type:"string",required:!0,secret:!1,example:"my-cluster"},{name:"instance",type:"string",required:!0,secret:!1,example:"my-instance"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[{name:"alloydb-ai-nl",type:"alloydb-ai-nl",description:'The "alloydb-ai-nl" tool leverages [AlloyDB AI](https://cloud.google.com/alloydb/ai) next-generation Natural Language support to provide the ability to query the database directly using natural language.',kind:"prebuilt",yamlFields:["nlConfig","nlConfigParameters"]}]},{slug:"alloydb-admin",sourceType:"alloydb-admin",title:"AlloyDB Admin",description:'The \\"alloydb-admin\\" source provides a client for the AlloyDB API.\\n',fields:[{name:"useClientOAuth",type:"boolean",required:!0,secret:!1,example:"true"}],tools:[{name:"alloydb-create-cluster",type:"alloydb-create-cluster",description:'The \\"alloydb-create-cluster\\" tool creates a new AlloyDB for PostgreSQL cluster in a specified project and location.\\n',kind:"prebuilt"},{name:"alloydb-create-instance",type:"alloydb-create-instance",description:'The \\"alloydb-create-instance\\" tool creates a new AlloyDB instance within a specified cluster.\\n',kind:"prebuilt"},{name:"alloydb-create-user",type:"alloydb-create-user",description:'The \\"alloydb-create-user\\" tool creates a new database user within a specified AlloyDB cluster.\\n',kind:"prebuilt"},{name:"alloydb-get-cluster",type:"alloydb-get-cluster",description:'The \\"alloydb-get-cluster\\" tool retrieves details for a specific AlloyDB cluster.\\n',kind:"prebuilt"},{name:"alloydb-get-instance",type:"alloydb-get-instance",description:'The \\"alloydb-get-instance\\" tool retrieves details for a specific AlloyDB instance.\\n',kind:"prebuilt"},{name:"alloydb-get-user",type:"alloydb-get-user",description:'The \\"alloydb-get-user\\" tool retrieves details for a specific AlloyDB user.\\n',kind:"prebuilt"},{name:"alloydb-list-clusters",type:"alloydb-list-clusters",description:'The \\"alloydb-list-clusters\\" tool lists the AlloyDB clusters in a given project and location.\\n',kind:"prebuilt"},{name:"alloydb-list-instances",type:"alloydb-list-instances",description:'The \\"alloydb-list-instances\\" tool lists the AlloyDB instances for a given project, cluster and location.\\n',kind:"prebuilt"},{name:"alloydb-list-users",type:"alloydb-list-users",description:'The \\"alloydb-list-users\\" tool lists all database users within an AlloyDB cluster.\\n',kind:"prebuilt"},{name:"alloydb-wait-for-operation",type:"alloydb-wait-for-operation",description:"Wait for a long-running AlloyDB operation to complete.\\n",kind:"prebuilt",yamlFields:["delay","maxDelay","multiplier","maxRetries"]}]},{slug:"bigquery",sourceType:"bigquery",title:"BigQuery",description:"BigQuery is Google Cloud's fully managed, petabyte-scale, and cost-effective analytics data warehouse that lets you run analytics over vast amounts of data in near real time. With BigQuery, there's no infrastructure to set up or manage, letting you focus on finding meaningful insights using GoogleSQL and taking advantage of flexible pricing models across on-demand and flat-rate options.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"}],tools:[{name:"bigquery-analyze-contribution",type:"bigquery-analyze-contribution",description:'A "bigquery-analyze-contribution" tool performs contribution analysis in BigQuery.',kind:"prebuilt"},{name:"bigquery-conversational-analytics",type:"bigquery-conversational-analytics",description:'A "bigquery-conversational-analytics" tool allows conversational interaction with a BigQuery source.',kind:"prebuilt"},{name:"bigquery-execute-sql",type:"bigquery-execute-sql",description:'A "bigquery-execute-sql" tool executes a SQL statement against BigQuery.',kind:"custom"},{name:"bigquery-forecast",type:"bigquery-forecast",description:'A "bigquery-forecast" tool forecasts time series data in BigQuery.',kind:"prebuilt"},{name:"bigquery-get-dataset-info",type:"bigquery-get-dataset-info",description:'A "bigquery-get-dataset-info" tool retrieves metadata for a BigQuery dataset.',kind:"prebuilt"},{name:"bigquery-get-table-info",type:"bigquery-get-table-info",description:'A "bigquery-get-table-info" tool retrieves metadata for a BigQuery table.',kind:"prebuilt"},{name:"bigquery-list-dataset-ids",type:"bigquery-list-dataset-ids",description:'A "bigquery-list-dataset-ids" tool returns all dataset IDs from the source.',kind:"prebuilt"},{name:"bigquery-list-table-ids",type:"bigquery-list-table-ids",description:'A "bigquery-list-table-ids" tool returns table IDs in a given BigQuery dataset.',kind:"prebuilt"},{name:"bigquery-search-catalog",type:"bigquery-search-catalog",description:'A "bigquery-search-catalog" tool allows to search for entries based on the provided query.',kind:"prebuilt"},{name:"bigquery-sql",type:"bigquery-sql",description:'A "bigquery-sql" tool executes a pre-defined SQL statement.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"bigquery-sql"},{slug:"bigtable",sourceType:"bigtable",title:"Bigtable",description:"Bigtable is a low-latency NoSQL database service for machine learning, operational analytics, and user-facing operations. It's a wide-column, key-value store that can scale to billions of rows and thousands of columns. With Bigtable, you can replicate your data to regions across the world for high availability and data resiliency.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"instance",type:"string",required:!0,secret:!1,example:"test-instance"}],tools:[{name:"bigtable-sql",type:"bigtable-sql",description:'A "bigtable-sql" tool executes a pre-defined SQL statement against a Google Cloud Bigtable instance.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"bigtable-sql"},{slug:"cassandra",sourceType:"cassandra",title:"Cassandra",description:"Apache Cassandra is a NoSQL distributed database known for its horizontal scalability, distributed architecture, and flexible schema definition.",fields:[{name:"hosts",type:"string",required:!0,secret:!1,example:""},{name:"keyspace",type:"string",required:!0,secret:!1,example:"my_keyspace"},{name:"protoVersion",type:"number",required:!0,secret:!1,example:"4"},{name:"username",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"caPath",type:"string",required:!1,secret:!1,example:"/path/to/ca.crt",comment:"Optional: path to CA certificate"},{name:"certPath",type:"string",required:!1,secret:!1,example:"/path/to/client.crt",comment:"Optional: path to client certificate"},{name:"keyPath",type:"string",required:!1,secret:!1,example:"/path/to/client.key",comment:"Optional: path to client key"},{name:"enableHostVerification",type:"boolean",required:!1,secret:!1,example:"true",comment:"Optional: enable host verification"}],tools:[{name:"cassandra-cql",type:"cassandra-cql",description:'A "cassandra-cql" tool executes a pre-defined CQL statement against a Cassandra database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"],hasAuthRequired:!0}],customToolType:"cassandra-cql"},{slug:"clickhouse",sourceType:"clickhouse",title:"ClickHouse",description:"ClickHouse is an open-source, OLTP database.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"clickhouse.example.com"},{name:"port",type:"number",required:!0,secret:!1,example:"8443"},{name:"database",type:"string",required:!0,secret:!1,example:"analytics"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"protocol",type:"string",required:!0,secret:!1,example:"https"},{name:"secure",type:"boolean",required:!0,secret:!1,example:"true"}],tools:[{name:"clickhouse-execute-sql",type:"clickhouse-execute-sql",description:'A "clickhouse-execute-sql" tool executes a SQL statement against a ClickHouse database.',kind:"custom",parameters:[{name:"sql",type:"string",required:!0,description:"The SQL statement to execute against the database"}]},{name:"clickhouse-list-databases",type:"clickhouse-list-databases",description:'A "clickhouse-list-databases" tool lists all databases in a ClickHouse instance.',kind:"prebuilt",yamlFields:["parameters"],hasAuthRequired:!0},{name:"clickhouse-list-tables",type:"clickhouse-list-tables",description:'A "clickhouse-list-tables" tool lists all tables in a specific ClickHouse database.',kind:"prebuilt",parameters:[{name:"database",type:"string",required:!0,description:"The database to list tables from."}],yamlFields:["parameters"],hasAuthRequired:!0},{name:"clickhouse-sql",type:"clickhouse-sql",description:'A "clickhouse-sql" tool executes SQL queries as prepared statements in ClickHouse.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"clickhouse-sql"},{slug:"cloud-sql-admin",sourceType:"cloud-sql-admin",title:"Cloud SQL Admin",description:'A \\"cloud-sql-admin\\" source provides a client for the Cloud SQL Admin API.\\n',fields:[{name:"useClientOAuth",type:"boolean",required:!0,secret:!1,example:"true"}],tools:[{name:"cloudsqlcloneinstance",type:"cloud-sql-clone-instance",description:"Clone a Cloud SQL instance.",kind:"prebuilt",yamlFields:["parameter","project","sourceInstanceName","destinationInstanceName","pointInTime","preferredZone","preferredSecondaryZone"]},{name:"cloudsqlcreatebackup",type:"cloud-sql-create-backup",description:"Creates a backup on a Cloud SQL instance.",kind:"prebuilt",parameters:[{name:"project",type:"string",required:!0,description:"The project ID."},{name:"instance",type:"string",required:!0,description:"The name of the instance to take a backup on. Does not include the project ID."},{name:"location",type:"string",required:!1,description:"(Optional) Location of the backup run."},{name:"backup_description",type:"string",required:!1,description:"(Optional) The description of this backup run."}]},{name:"cloudsqlcreatedatabase",type:"cloud-sql-create-database",description:"Create a new database in a Cloud SQL instance.",kind:"prebuilt",parameters:[{name:"project",type:"string",required:!0,description:"The project ID."},{name:"instance",type:"string",required:!0,description:"The ID of the instance where the database will be created."},{name:"name",type:"string",required:!0,description:"The name for the new database. Must be unique within the instance."}]},{name:"cloudsqlcreateusers",type:"cloud-sql-create-users",description:"Create a new user in a Cloud SQL instance.",kind:"prebuilt"},{name:"cloudsqlgetinstances",type:"cloud-sql-get-instance",description:"Get a Cloud SQL instance resource.",kind:"prebuilt"},{name:"cloudsqllistdatabases",type:"cloud-sql-admin",description:"List Cloud SQL databases in an instance.",kind:"prebuilt"},{name:"cloudsqllistinstances",type:"cloud-sql-admin",description:"List Cloud SQL instances in a project.\\n",kind:"prebuilt"},{name:"cloudsqlmssqlcreateinstance",type:"cloud-sql-mssql-create-instance",description:"Create a Cloud SQL for SQL Server instance.",kind:"prebuilt",yamlFields:["parameter","project","databaseVersion","rootPassword","editionPreset"]},{name:"cloudsqlmysqlcreateinstance",type:"cloud-sql-admin",description:"Create a Cloud SQL for MySQL instance.",kind:"prebuilt"},{name:"cloudsqlpgcreateinstances",type:"cloud-sql-postgres-create-instance",description:"Create a Cloud SQL for PostgreSQL instance.",kind:"prebuilt",yamlFields:["parameter","project","databaseVersion","rootPassword","editionPreset"]},{name:"cloudsqlpgupgradeprecheck",type:"postgres-upgrade-precheck",description:"Perform a pre-check for a Cloud SQL for PostgreSQL major version upgrade.",kind:"prebuilt",yamlFields:["parameter","project","instance","targetDatabaseVersion"]},{name:"cloudsqlrestorebackup",type:"cloud-sql-restore-backup",description:"Restores a backup of a Cloud SQL instance.",kind:"prebuilt",parameters:[{name:"target_project",type:"string",required:!0,description:"The project ID of the instance to restore the backup onto."},{name:"target_instance",type:"string",required:!0,description:"The instance to restore the backup onto. Does not include the project ID."},{name:"backup_id",type:"string",required:!0,description:"The identifier of the backup being restored."},{name:"source_project",type:"string",required:!1,description:"(Optional) The project ID of the instance that the backup belongs to."},{name:"source_instance",type:"string",required:!1,description:"(Optional) Cloud SQL instance ID of the instance that the backup belongs to."}]},{name:"cloudsqlwaitforoperation",type:"cloud-sql-wait-for-operation",description:"Wait for a long-running Cloud SQL operation to complete.",kind:"prebuilt",yamlFields:["delay","maxDelay","multiplier","maxRetries"]}]},{slug:"cloud-sql-mssql",sourceType:"cloud-sql-mssql",title:"Cloud SQL for SQL Server",description:"Cloud SQL for SQL Server is a fully-managed database service for SQL Server.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project"},{name:"region",type:"string",required:!0,secret:!1,example:"my-region"},{name:"instance",type:"string",required:!0,secret:!1,example:"my-instance"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[]},{slug:"cloud-sql-mysql",sourceType:"cloud-sql-mysql",title:"Cloud SQL for MySQL",description:"Cloud SQL for MySQL is a fully-managed database service for MySQL.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"region",type:"string",required:!0,secret:!1,example:"us-central1"},{name:"instance",type:"string",required:!0,secret:!1,example:"my-instance"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[]},{slug:"cloud-sql-pg",sourceType:"cloud-sql-postgres",title:"Cloud SQL for PostgreSQL",description:"Cloud SQL for PostgreSQL is a fully-managed database service for Postgres.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"region",type:"string",required:!0,secret:!1,example:"us-central1"},{name:"instance",type:"string",required:!0,secret:!1,example:"my-instance"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[{name:"vector-assist-apply-spec",type:"vector-assist-apply-spec",description:'The "vector-assist-apply-spec" tool automatically executes all SQL recommendations associated with a specific vector specification or table to finalize the vector search setup.',kind:"prebuilt",parameters:[{name:"spec_id",type:"string",required:"no",description:"Unique ID of the vector specification to apply."},{name:"table_name",type:"string",required:"no",description:"Target table name for applying the vector specification."},{name:"column_name",type:"string",required:"no",description:"Text or vector column name to uniquely identify the specification."},{name:"schema_name",type:"string",required:"no",description:"Schema name for the target table."}]},{name:"vector-assist-define-spec",type:"vector-assist-define-spec",description:`The "vector-assist-define-spec" tool defines a new vector specification by capturing the user's intent and requirements for a vector search workload, generating SQL recommendations for setting up database, embeddings, and vector indexes.`,kind:"prebuilt",parameters:[{name:"table_name",type:"string",required:"yes",description:"Target table name for setting up the vector workload."},{name:"schema_name",type:"string",required:"no",description:"Name of the schema containing the target table."},{name:"spec_id",type:"string",required:"no",description:"Unique ID for the vector specification; auto-generated if omitted."},{name:"vector_column_name",type:"string",required:"no",description:"Name of the column containing the vector embeddings."},{name:"text_column_name",type:"string",required:"no",description:"Name of the text column for setting up vector search."},{name:"vector_index_type",type:"string",required:"no",description:"Type of vector index ('hnsw', 'ivfflat', or 'scann')."},{name:"embeddings_available",type:"boolean",required:"no",description:"Indicates if vector embeddings already exist in the table."},{name:"num_vectors",type:"integer",required:"no",description:"Expected total number of vectors in the dataset."},{name:"dimensionality",type:"integer",required:"no",description:"Dimension of existing vectors or the chosen embedding model."},{name:"embedding_model",type:"string",required:"no",description:"Model to be used for generating vector embeddings."},{name:"prefilter_column_names",type:"array",required:"no",description:"List of columns to use for prefiltering vector queries."},{name:"distance_func",type:"string",required:"no",description:"Distance function for comparing vectors ('cosine', 'ip', 'l2', 'l1')."},{name:"quantization",type:"string",required:"no",description:"Quantization method for vector indexes ('none', 'halfvec', 'bit')."},{name:"memory_budget_kb",type:"integer",required:"no",description:"Maximum memory (in KB) the index can use during build."},{name:"target_recall",type:"float",required:"no",description:"Target recall rate for standard vector queries using this index."},{name:"target_top_k",type:"integer",required:"no",description:"Number of top results (top-K) to retrieve per query."},{name:"tune_vector_index",type:"boolean",required:"no",description:"Indicates whether automatic tuning is required for the index."}]},{name:"vector-assist-generate-query",type:"vector-assist-generate-query",description:'The "vector-assist-generate-query" tool produces optimized SQL queries for vector search, leveraging metadata and specifications to enable semantic and similarity searches.',kind:"prebuilt",parameters:[{name:"spec_id",type:"string",required:"no",description:"Unique ID of the vector spec for query generation."},{name:"table_name",type:"string",required:"no",description:"Target table name for generating the vector query."},{name:"schema_name",type:"string",required:"no",description:"Schema name for the query's target table."},{name:"column_name",type:"string",required:"no",description:"Text or vector column name identifying the specific spec."},{name:"search_text",type:"string",required:"no",description:"Text string to search for; embeddings are auto-generated."},{name:"search_vector",type:"string",required:"no",description:"Vector to search for; use instead of search_text."},{name:"output_column_names",type:"array",required:"no",description:"List of columns to retrieve in the search results."},{name:"top_k",type:"integer",required:"no",description:"Number of nearest neighbors to return (defaults to 10)."},{name:"filter_expressions",type:"array",required:"no",description:"List of filter expressions applied to the vector query."},{name:"target_recall",type:"float",required:"no",description:"Target recall rate, overriding the spec-level default."},{name:"iterative_index_search",type:"boolean",required:"no",description:"Enables iterative search for filtered queries to guarantee results."}]},{name:"vector-assist-modify-spec",type:"vector-assist-modify-spec",description:'The "vector-assist-modify-spec" tool modifies an existing vector specification with new parameters or overrides, recalculating the generated SQL recommendations to match the updated requirements.',kind:"prebuilt",parameters:[{name:"spec_id",type:"string",required:"yes",description:"Unique ID of the vector specification to modify."},{name:"table_name",type:"string",required:"no",description:"New table name for the vector workload setup."},{name:"schema_name",type:"string",required:"no",description:"New schema name containing the target table."},{name:"vector_column_name",type:"string",required:"no",description:"New name for the column containing vector embeddings."},{name:"text_column_name",type:"string",required:"no",description:"New name for the text column for vector search."},{name:"vector_index_type",type:"string",required:"no",description:"New vector index type ('hnsw', 'ivfflat', or 'scann')."},{name:"embeddings_available",type:"boolean",required:"no",description:"Update if vector embeddings already exist in the table."},{name:"num_vectors",type:"integer",required:"no",description:"Update the expected total number of vectors."},{name:"dimensionality",type:"integer",required:"no",description:"Update the dimension of vectors or the embedding model."},{name:"embedding_model",type:"string",required:"no",description:"Update the model used for generating vector embeddings."},{name:"prefilter_column_names",type:"array",required:"no",description:"Update the columns used for prefiltering vector queries."},{name:"distance_func",type:"string",required:"no",description:"Update the distance function ('cosine', 'ip', 'l2', 'l1')."},{name:"quantization",type:"string",required:"no",description:"Update the quantization method ('none', 'halfvec', 'bit')."},{name:"memory_budget_kb",type:"integer",required:"no",description:"Update maximum memory (in KB) for index building."},{name:"target_recall",type:"float",required:"no",description:"Update the target recall rate for the index."},{name:"target_top_k",type:"integer",required:"no",description:"Update the number of top results (top-K) to retrieve."},{name:"tune_vector_index",type:"boolean",required:"no",description:"Update whether automatic tuning is required for the index."}]}]},{slug:"cloud-storage",sourceType:"cloud-storage",title:"Cloud Storage",description:"Cloud Storage is Google Cloud's managed service for storing unstructured objects (files) in buckets. Toolbox connects at the project level, allowing tools to list buckets, list objects, read object metadata and content, mutate objects, and transfer objects between Cloud Storage and the server filesystem.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"}],tools:[{name:"cloud-storage-copy-object",type:"cloud-storage-copy-object",description:'A "cloud-storage-copy-object" tool copies a Cloud Storage object to another object, including across buckets.',kind:"prebuilt",parameters:[{name:"source_bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket containing the source object."},{name:"source_object",type:"string",required:!0,description:"Full source object name (path) within the source bucket, e.g. path/to/file.txt."},{name:"destination_bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket to copy into."},{name:"destination_object",type:"string",required:!0,description:"Full destination object name (path) within the destination bucket."}]},{name:"cloud-storage-create-bucket",type:"cloud-storage-create-bucket",description:'A "cloud-storage-create-bucket" tool creates a Cloud Storage bucket in the configured source project.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket to create."},{name:"location",type:"string",required:!1,description:'Location for the bucket, e.g. "US", "EU", or "us-central1". Omit to use the Cloud Storage service default.'},{name:"uniform_bucket_level_access",type:"boolean",required:!1,description:"Whether to enable uniform bucket-level access on the bucket. Defaults to false."}]},{name:"cloud-storage-delete-bucket",type:"cloud-storage-delete-bucket",description:'A "cloud-storage-delete-bucket" tool deletes an empty Cloud Storage bucket.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the empty Cloud Storage bucket to delete."}]},{name:"cloud-storage-delete-object",type:"cloud-storage-delete-object",description:'A "cloud-storage-delete-object" tool deletes a Cloud Storage object.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket containing the object to delete."},{name:"object",type:"string",required:!0,description:"Full object name (path) within the bucket, e.g. path/to/file.txt."}]},{name:"cloud-storage-download-object",type:"cloud-storage-download-object",description:'A "cloud-storage-download-object" tool downloads a Cloud Storage object to an absolute path on the Toolbox server filesystem.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket containing the object."},{name:"object",type:"string",required:!0,description:"Full object name (path) within the bucket, e.g. path/to/file.txt."},{name:"destination",type:"string",required:!0,description:"Absolute local filesystem path where the object will be written. Relative paths and paths containing .. are rejected."},{name:"overwrite",type:"boolean",required:!1,description:"If true, overwrite the destination when it already exists. If false (default), return an error when it exists."}]},{name:"cloud-storage-get-bucket-iam-policy",type:"cloud-storage-get-bucket-iam-policy",description:'A "cloud-storage-get-bucket-iam-policy" tool returns IAM policy bindings for a Cloud Storage bucket.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket whose IAM policy should be returned."}]},{name:"cloud-storage-get-bucket-metadata",type:"cloud-storage-get-bucket-metadata",description:'A "cloud-storage-get-bucket-metadata" tool returns metadata for a Cloud Storage bucket.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket to inspect."}]},{name:"cloud-storage-get-object-metadata",type:"cloud-storage-get-object-metadata",description:'A "cloud-storage-get-object-metadata" tool returns metadata for a Cloud Storage object without reading the object payload.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket containing the object."},{name:"object",type:"string",required:!0,description:"Full object name (path) within the bucket, e.g. path/to/file.txt."}]},{name:"cloud-storage-list-buckets",type:"cloud-storage-list-buckets",description:'A "cloud-storage-list-buckets" tool lists Cloud Storage buckets in a project, with optional prefix filtering and pagination.',kind:"prebuilt",parameters:[{name:"project",type:"string",required:!1,description:"Project ID to list buckets in. When empty, the source's configured project is used."},{name:"prefix",type:"string",required:!1,description:"Filter results to buckets whose names begin with this prefix."},{name:"max_results",type:"integer",required:!1,description:"Maximum number of buckets to return per page. A value of 0 uses the API default (1000); negative values and values above 1000 are rejected."},{name:"page_token",type:"string",required:!1,description:"A previously-returned page token for retrieving the next page of results."}]},{name:"cloud-storage-list-objects",type:"cloud-storage-list-objects",description:'A "cloud-storage-list-objects" tool lists objects in a Cloud Storage bucket, with optional prefix filtering and delimiter-based grouping.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket to list objects from."},{name:"prefix",type:"string",required:!1,description:"Filter results to objects whose names begin with this prefix."},{name:"delimiter",type:"string",required:!1,description:"Delimiter used to group object names (typically '/'). When set, common prefixes are returned as prefixes."},{name:"max_results",type:"integer",required:!1,description:"Maximum number of objects to return per page. A value of 0 uses the API default (1000); negative values and values above 1000 are rejected."},{name:"page_token",type:"string",required:!1,description:"A previously-returned page token for retrieving the next page of results."}]},{name:"cloud-storage-move-object",type:"cloud-storage-move-object",description:'A "cloud-storage-move-object" tool atomically moves or renames a Cloud Storage object within the same bucket.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket containing the object to move."},{name:"source_object",type:"string",required:!0,description:"Full source object name (path) within the bucket, e.g. path/to/file.txt."},{name:"destination_object",type:"string",required:!0,description:"Full destination object name (path) within the same bucket."}]},{name:"cloud-storage-read-object",type:"cloud-storage-read-object",description:'A "cloud-storage-read-object" tool reads the UTF-8 text content of a Cloud Storage object, optionally constrained to a byte range.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket containing the object."},{name:"object",type:"string",required:!0,description:"Full object name (path) within the bucket, e.g. path/to/file.txt."},{name:"range",type:"string",required:!1,description:"Optional HTTP byte range, e.g. bytes=0-999 (first 1000 bytes), bytes=-500 (last 500 bytes), or bytes=500- (from byte 500 to end). Empty reads the full object."}]},{name:"cloud-storage-upload-object",type:"cloud-storage-upload-object",description:'A "cloud-storage-upload-object" tool uploads a local file from the Toolbox server filesystem to a Cloud Storage object.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket to upload into."},{name:"object",type:"string",required:!0,description:"Full object name (path) within the bucket, e.g. path/to/file.txt."},{name:"source",type:"string",required:!0,description:"Absolute local filesystem path of the file to upload. Relative paths and paths containing .. are rejected."},{name:"content_type",type:"string",required:!1,description:"MIME type to record on the uploaded object. When empty, it is inferred from the source file extension when possible."}]},{name:"cloud-storage-write-object",type:"cloud-storage-write-object",description:'A "cloud-storage-write-object" tool writes text content directly to a Cloud Storage object.',kind:"prebuilt",parameters:[{name:"bucket",type:"string",required:!0,description:"Name of the Cloud Storage bucket to write into."},{name:"object",type:"string",required:!0,description:"Full object name (path) within the bucket, e.g. path/to/file.txt."},{name:"content",type:"string",required:!0,description:"Text content to write to the Cloud Storage object."},{name:"content_type",type:"string",required:!1,description:"MIME type to record on the written object. When empty, Cloud Storage auto-detects from the content."}]}]},{slug:"cloudgda",sourceType:"cloud-gemini-data-analytics",title:"Gemini Data Analytics",description:'A "cloud-gemini-data-analytics" source provides a client for the Gemini Data Analytics API.',fields:[{name:"projectId",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"projectId",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"useClientOAuth",type:"boolean",required:!0,secret:!1,example:"true"}],tools:[{name:"cloud-gda-query",type:"cloud-gemini-data-analytics-query",description:"A tool to convert natural language queries into SQL statements using the Gemini Data Analytics QueryData API.",kind:"prebuilt",yamlFields:["location","context","generationOptions"]},{name:"conversational-analytics-ask-data-agent",type:"conversational-analytics-ask-data-agent",description:'A "conversational-analytics-ask-data-agent" tool allows conversational interaction with a Conversational Analytics source.',kind:"prebuilt",yamlFields:["location","maxResults"]},{name:"conversational-analytics-get-data-agent-info",type:"conversational-analytics-get-data-agent-info",description:'A "conversational-analytics-get-data-agent-info" tool allows retrieving information about a specific Conversational Analytics data agent.',kind:"prebuilt",yamlFields:["location"]},{name:"conversational-analytics-list-accessible-data-agents",type:"conversational-analytics-list-accessible-data-agents",description:'A "conversational-analytics-list-accessible-data-agents" tool allows listing accessible Conversational Analytics data agents.',kind:"prebuilt",yamlFields:["location"]}]},{slug:"cloudhealthcare",sourceType:"cloud-healthcare",title:"Cloud Healthcare",description:"The Cloud Healthcare API provides a managed solution for storing and accessing healthcare data in Google Cloud, providing a critical bridge between existing care systems and applications hosted on Google Cloud.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"region",type:"string",required:!0,secret:!1,example:"us-central1"},{name:"dataset",type:"string",required:!0,secret:!1,example:"my-healthcare-dataset-id"}],tools:[{name:"cloud-healthcare-fhir-fetch-page",type:"cloud-healthcare-fhir-fetch-page",description:'A "cloud-healthcare-fhir-fetch-page" tool fetches a page of FHIR resources from a given URL.',kind:"prebuilt",yamlFields:["field","pageURL"]},{name:"cloud-healthcare-fhir-patient-everything",type:"cloud-healthcare-fhir-patient-everything",description:'A "cloud-healthcare-fhir-patient-everything" tool retrieves all information for a given patient.',kind:"prebuilt",yamlFields:["field","patientID","resourceTypesFilter","sinceFilter","storeID"]},{name:"cloud-healthcare-fhir-patient-search",type:"cloud-healthcare-fhir-patient-search",description:'A "cloud-healthcare-fhir-patient-search" tool searches for patients in a FHIR store.',kind:"prebuilt",yamlFields:["field","active","city","country","postalcode","state","addressSubstring","birthDateRange","deathDateRange","deceased","email","gender","addressUse","givenName","familyName","phone","language","identifier","summary","storeID"]},{name:"cloud-healthcare-get-dataset",type:"cloud-healthcare-get-dataset",description:'A "cloud-healthcare-get-dataset" tool retrieves metadata for the Healthcare dataset in the source.',kind:"prebuilt"},{name:"cloud-healthcare-get-dicom-store-metrics",type:"cloud-healthcare-get-dicom-store-metrics",description:'A "cloud-healthcare-get-dicom-store-metrics" tool retrieves metrics for a DICOM store.',kind:"prebuilt",yamlFields:["field","storeID"]},{name:"cloud-healthcare-get-dicom-store",type:"cloud-healthcare-get-dicom-store",description:'A "cloud-healthcare-get-dicom-store" tool retrieves information about a DICOM store.',kind:"prebuilt",yamlFields:["field","storeID"]},{name:"cloud-healthcare-get-fhir-resource",type:"cloud-healthcare-get-fhir-resource",description:'A "cloud-healthcare-get-fhir-resource" tool retrieves a specific FHIR resource.',kind:"prebuilt",yamlFields:["field","resourceType","resourceID","storeID"]},{name:"cloud-healthcare-get-fhir-store-metrics",type:"cloud-healthcare-get-fhir-store-metrics",description:'A "cloud-healthcare-get-fhir-store-metrics" tool retrieves metrics for a FHIR store.',kind:"prebuilt",yamlFields:["field","storeID"]},{name:"cloud-healthcare-get-fhir-store",type:"cloud-healthcare-get-fhir-store",description:'A "cloud-healthcare-get-fhir-store" tool retrieves information about a FHIR store.',kind:"prebuilt",yamlFields:["field","storeID"]},{name:"cloud-healthcare-list-dicom-stores",type:"cloud-healthcare-list-dicom-stores",description:'A "cloud-healthcare-list-dicom-stores" lists the available DICOM stores in the healthcare dataset.',kind:"prebuilt"},{name:"cloud-healthcare-list-fhir-stores",type:"cloud-healthcare-list-fhir-stores",description:'A "cloud-healthcare-list-fhir-stores" lists the available FHIR stores in the healthcare dataset.',kind:"prebuilt"},{name:"cloud-healthcare-retrieve-rendered-dicom-instance",type:"cloud-healthcare-retrieve-rendered-dicom-instance",description:'A "cloud-healthcare-retrieve-rendered-dicom-instance" tool retrieves a rendered DICOM instance from a DICOM store.',kind:"prebuilt",yamlFields:["field","StudyInstanceUID","SeriesInstanceUID","SOPInstanceUID","FrameNumber","storeID"]},{name:"cloud-healthcare-search-dicom-instances",type:"cloud-healthcare-search-dicom-instances",description:'A "cloud-healthcare-search-dicom-instances" tool searches for DICOM instances in a DICOM store.',kind:"prebuilt",yamlFields:["field","StudyInstanceUID","PatientName","PatientID","AccessionNumber","ReferringPhysicianName","StudyDate","SeriesInstanceUID","Modality","SOPInstanceUID","fuzzymatching","includefield","storeID"]},{name:"cloud-healthcare-search-dicom-series",type:"cloud-healthcare-search-dicom-series",description:'A "cloud-healthcare-search-dicom-series" tool searches for DICOM series in a DICOM store.',kind:"prebuilt",yamlFields:["field","StudyInstanceUID","PatientName","PatientID","AccessionNumber","ReferringPhysicianName","StudyDate","SeriesInstanceUID","Modality","fuzzymatching","includefield","storeID"]},{name:"cloud-healthcare-search-dicom-studies",type:"cloud-healthcare-search-dicom-studies",description:'A "cloud-healthcare-search-dicom-studies" tool searches for DICOM studies in a DICOM store.',kind:"prebuilt",yamlFields:["field","StudyInstanceUID","PatientName","PatientID","AccessionNumber","ReferringPhysicianName","StudyDate","fuzzymatching","includefield","storeID"]}]},{slug:"cloudloggingadmin",sourceType:"cloud-logging-admin",title:"Cloud Logging Admin",description:"The Cloud Logging Admin source enables tools to interact with the Cloud Logging API, allowing for the retrieval of log names, monitored resource types, and the querying of log data.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"}],tools:[{name:"cloud-logging-admin-list-log-names",type:"cloud-logging-admin-list-log-names",description:'A "cloud-logging-admin-list-log-names" tool lists the log names in the project.',kind:"prebuilt",parameters:[{name:"limit",type:"integer",required:!1,description:"Maximum number of log entries to return (default: 200)."}],yamlFields:["parameter","limit"]},{name:"cloud-logging-admin-list-resource-types",type:"cloud-logging-admin-list-resource-types",description:'A "cloud-logging-admin-list-resource-types" tool lists the monitored resource types.',kind:"prebuilt"},{name:"cloud-logging-admin-query-logs",type:"cloud-logging-admin-query-logs",description:'A "cloud-logging-admin-query-logs" tool queries log entries.',kind:"prebuilt",parameters:[{name:"filter",type:"string",required:!1,description:"Cloud Logging filter query. Common fields: resource.type, resource.labels.*, logName, severity, textPayload, jsonPayload.*, protoPayload.*, labels.*, httpRequest.*. Operators: =, !=, <, <=, >, >=, :, =~, AND, OR, NOT."},{name:"newestFirst",type:"boolean",required:!1,description:"Set to true for newest logs first. Defaults to oldest first."},{name:"startTime",type:"string",required:!1,description:"Start time in RFC3339 format (e.g., 2025-12-09T00:00:00Z). Defaults to 30 days ago."},{name:"endTime",type:"string",required:!1,description:"End time in RFC3339 format (e.g., 2025-12-09T23:59:59Z). Defaults to now."},{name:"verbose",type:"boolean",required:!1,description:"Include additional fields (insertId, trace, spanId, httpRequest, labels, operation, sourceLocation). Defaults to false."},{name:"limit",type:"integer",required:!1,description:"Maximum number of log entries to return. Default: 200."}],yamlFields:["parameter","filter","newestFirst","startTime","endTime","verbose","limit"]}]},{slug:"cloudmonitoring",sourceType:"cloud-monitoring",title:"Cloud Monitoring",description:'A "cloud-monitoring" source provides a client for the Cloud Monitoring API.',fields:[{name:"useClientOAuth",type:"boolean",required:!0,secret:!1,example:"true"}],tools:[{name:"cloud-monitoring-query-prometheus",type:"cloud-monitoring-query-prometheus",description:'The "cloud-monitoring-query-prometheus" tool fetches time series metrics for a project using a given prometheus query.',kind:"prebuilt",parameters:[{name:"projectId",type:"string",required:!1,description:"The Google Cloud project ID."},{name:"query",type:"string",required:!1,description:"The Prometheus query to execute."}]}]},{slug:"couchbase",sourceType:"couchbase",title:"Couchbase",description:'A "couchbase" source connects to a Couchbase database.',fields:[{name:"connectionString",type:"string",required:!0,secret:!1,example:"couchbase://localhost"},{name:"bucket",type:"string",required:!0,secret:!1,example:"travel-sample"},{name:"scope",type:"string",required:!0,secret:!1,example:"inventory"},{name:"username",type:"string",required:!0,secret:!1,example:"Administrator"},{name:"password",type:"string",required:!0,secret:!0,example:"password"}],tools:[{name:"couchbase-sql",type:"couchbase-sql",description:'A "couchbase-sql" tool executes a pre-defined SQL statement against a Couchbase database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"],hasAuthRequired:!0}],customToolType:"couchbase-sql"},{slug:"dataproc",sourceType:"dataproc",title:"Dataproc Clusters",description:"Google Cloud Dataproc Clusters lets you provision and manage Apache Spark and Hadoop clusters.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project"},{name:"region",type:"string",required:!0,secret:!1,example:"us-central1"}],tools:[{name:"dataproc-get-cluster",type:"dataproc-get-cluster",description:'A "dataproc-get-cluster" tool retrieves a specific Dataproc cluster from the source.',kind:"prebuilt",hasAuthRequired:!0},{name:"dataproc-get-job",type:"dataproc-get-job",description:'A "dataproc-get-job" tool retrieves a specific Dataproc job from the source.',kind:"prebuilt",hasAuthRequired:!0},{name:"dataproc-list-clusters",type:"dataproc-list-clusters",description:'A "dataproc-list-clusters" tool returns a list of Dataproc clusters from the source.',kind:"prebuilt",hasAuthRequired:!0},{name:"dataproc-list-jobs",type:"dataproc-list-jobs",description:'A "dataproc-list-jobs" tool returns a list of Dataproc jobs from the source.',kind:"prebuilt",hasAuthRequired:!0}]},{slug:"dgraph",sourceType:"dgraph",title:"Dgraph",description:"Dgraph is fully open-source, built-for-scale graph database for Gen AI workloads",fields:[{name:"dgraphUrl",type:"string",required:!0,secret:!1,example:"https://xxxx.cloud.dgraph.io"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"apiKey",type:"string",required:!0,secret:!0,example:""}],tools:[{name:"dgraph-dql",type:"dgraph-dql",description:'A "dgraph-dql" tool executes a pre-defined DQL statement against a Dgraph database.',kind:"prebuilt",yamlFields:["statement","isQuery","timeout","parameters"]}]},{slug:"elasticsearch",sourceType:"elasticsearch",title:"Elasticsearch",description:"Elasticsearch is a distributed, free and open search and analytics engine for all types of data, including textual, numerical, geospatial, structured, and unstructured.",fields:[{name:"addresses",type:"string",required:!0,secret:!1,example:""},{name:"apikey",type:"string",required:!0,secret:!0,example:"my-api-key"}],tools:[{name:"elasticsearch-esql",type:"elasticsearch-esql",description:"Execute ES|QL queries.",kind:"custom",yamlFields:["query","format","timeout","parameters"]},{name:"elasticsearch-execute-esql",type:"elasticsearch-execute-esql",description:"Execute arbitrary ES|QL statements.",kind:"custom",parameters:[{name:"query",type:"string",required:!0,description:"The ES"}],yamlFields:["format"]}],customToolType:"elasticsearch-esql"},{slug:"firebird",sourceType:"firebird",title:"Firebird",description:"Firebird is a powerful, cross-platform, and open-source relational database.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"localhost"},{name:"port",type:"number",required:!0,secret:!1,example:"3050"},{name:"database",type:"string",required:!0,secret:!1,example:"/path/to/your/database.fdb"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[{name:"firebird-execute-sql",type:"firebird-execute-sql",description:'A "firebird-execute-sql" tool executes a SQL statement against a Firebird database.',kind:"custom"},{name:"firebird-sql",type:"firebird-sql",description:'A "firebird-sql" tool executes a pre-defined SQL statement against a Firebird database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"firebird-sql"},{slug:"firestore",sourceType:"firestore",title:"Firestore",description:"Firestore is a NoSQL document database built for automatic scaling, high performance, and ease of application development. It's a fully managed, serverless database that supports mobile, web, and server development.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"}],tools:[{name:"firestore-add-documents",type:"firestore-add-documents",description:'A "firestore-add-documents" tool adds document to a given collection path.',kind:"prebuilt",parameters:[{name:"collectionPath",type:"string",required:"yes",description:"The path of the collection where the document will be added"},{name:"documentData",type:"map",required:"yes",description:"The data to be added as a document to the given collection. Must use [Firestore's native JSON format](https://cloud.google.com/firestore/docs/reference/rest/Shared.Types/ArrayValue#Value) with typed values"},{name:"returnData",type:"boolean",required:"no",description:"If set to true, the output will include the data of the created document. Defaults to false to help avoid overloading the context"}]},{name:"firestore-delete-documents",type:"firestore-delete-documents",description:'A "firestore-delete-documents" tool deletes multiple documents from Firestore by their paths.',kind:"prebuilt"},{name:"firestore-get-documents",type:"firestore-get-documents",description:'A "firestore-get-documents" tool retrieves multiple documents from Firestore by their paths.',kind:"prebuilt"},{name:"firestore-get-rules",type:"firestore-get-rules",description:'A "firestore-get-rules" tool retrieves the active Firestore security rules for the current project.',kind:"prebuilt"},{name:"firestore-list-collections",type:"firestore-list-collections",description:'A "firestore-list-collections" tool lists collections in Firestore, either at the root level or as subcollections of a document.',kind:"prebuilt"},{name:"firestore-query-collection",type:"firestore",description:'A "firestore-query-collection" tool allow to query collections in Firestore.',kind:"prebuilt"},{name:"firestore-query",type:"firestore-query",description:"Query a Firestore collection with parameterizable filters and Firestore native JSON value types",kind:"prebuilt",parameters:[{name:"type",type:"string",required:"yes",description:"Must be firestore-query"},{name:"source",type:"string",required:"yes",description:"Name of the Firestore source to use"},{name:"description",type:"string",required:"yes",description:"Description of what this tool does"},{name:"collectionPath",type:"string",required:"yes",description:"Path to the collection to query (supports templates)"},{name:"filters",type:"string",required:"no",description:"JSON string defining query filters (supports templates)"},{name:"select",type:"array",required:"no",description:"Fields to select from documents(supports templates - string or array)"},{name:"orderBy",type:"object",required:"no",description:"Ordering configuration with field and direction(supports templates for the value of field or direction)"},{name:"limit",type:"integer",required:"no",description:"Maximum number of documents to return (default: 100) (supports templates)"},{name:"analyzeQuery",type:"boolean",required:"no",description:"Whether to analyze query performance (default: false)"},{name:"parameters",type:"array",required:"yes",description:"Parameter definitions for template substitution"}]},{name:"firestore-update-document",type:"firestore-update-document",description:'A "firestore-update-document" tool updates an existing document in Firestore.',kind:"prebuilt",parameters:[{name:"documentPath",type:"string",required:"yes",description:"The path of the document which needs to be updated"},{name:"documentData",type:"map",required:"yes",description:"The data to update in the document. Must use [Firestore's native JSON format](https://cloud.google.com/firestore/docs/reference/rest/Shared.Types/ArrayValue#Value) with typed values"},{name:"updateMask",type:"array",required:"no",description:"The selective fields to update. If not provided, all fields in documentData will be updated. When provided, only the specified fields will be updated. Fields referenced in the mask but not present in documentData will be deleted from the document"},{name:"returnData",type:"boolean",required:"no",description:"If set to true, the output will include the data of the updated document. Defaults to false to help avoid overloading the context"}]},{name:"firestore-validate-rules",type:"firestore-validate-rules",description:'A "firestore-validate-rules" tool validates Firestore security rules syntax and semantic correctness without deploying them. It provides detailed error reporting with source positions and code snippets.',kind:"prebuilt"}]},{slug:"http",sourceType:"http",title:"HTTP",description:"The HTTP source enables the Toolbox to retrieve data from a remote server using HTTP requests.",fields:[{name:"baseUrl",type:"string",required:!0,secret:!1,example:"https://api.example.com/data"},{name:"timeout",type:"string",required:!0,secret:!1,example:"10s",comment:"default to 30s"},{name:"headers",type:"string",required:!0,secret:!1,example:""},{name:"queryParams",type:"string",required:!0,secret:!1,example:""}],tools:[{name:"http-tool",type:"http",description:'A "http" tool sends out an HTTP request to an HTTP endpoint.',kind:"prebuilt",yamlFields:["path","method","headers","requestBody","queryParams","bodyParams","headerParams"]}]},{slug:"knowledge-catalog",sourceType:"dataplex",title:"Knowledge Catalog",description:"Knowledge Catalog is a unified, intelligent governance solution for data and AI assets in Google Cloud. Knowledge Catalog powers AI, analytics, and business intelligence at scale.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"}],tools:[{name:"knowledge-catalog-lookup-context",type:"dataplex-lookup-context",description:'A "dataplex-lookup-context" tool provides rich metadata of one or more data assets along with their relationships.',kind:"prebuilt"},{name:"knowledge-catalog-lookup-entry",type:"dataplex-lookup-entry",description:'A "dataplex-lookup-entry" tool returns details of a particular entry in Knowledge Catalog.',kind:"prebuilt"},{name:"knowledge-catalog-search-aspect-types",type:"dataplex-search-aspect-types",description:'A "dataplex-search-aspect-types" tool allows to to find aspect types relevant to the query.',kind:"prebuilt"},{name:"knowledge-catalog-search-dq-scans",type:"dataplex-search-dq-scans",description:'A "dataplex-search-dq-scans" tool allows to search for data quality scans based on the provided parameters.',kind:"prebuilt"},{name:"knowledge-catalog-search-entries",type:"dataplex-search-entries",description:'A "dataplex-search-entries" tool allows to search for entries based on the provided query.',kind:"prebuilt"}]},{slug:"looker",sourceType:"looker",title:"Looker",description:"Looker is a business intelligence tool that also provides a semantic layer.",fields:[{name:"base_url",type:"string",required:!0,secret:!1,example:""},{name:"client_id",type:"string",required:!0,secret:!1,example:""},{name:"client_secret",type:"string",required:!0,secret:!0,example:""},{name:"verify_ssl",type:"string",required:!0,secret:!1,example:""},{name:"timeout",type:"string",required:!0,secret:!1,example:"600s"},{name:"use_client_oauth",type:"string",required:!0,secret:!1,example:""},{name:"show_hidden_models",type:"string",required:!0,secret:!1,example:""},{name:"show_hidden_explores",type:"string",required:!0,secret:!1,example:""},{name:"show_hidden_fields",type:"string",required:!0,secret:!1,example:""}],tools:[{name:"looker-add-dashboard-element",type:"looker-add-dashboard-element",description:'"looker-add-dashboard-element" creates a dashboard element in the given dashboard.',kind:"prebuilt"},{name:"looker-add-dashboard-filter",type:"looker-add-dashboard-filter",description:'The "looker-add-dashboard-filter" tool adds a filter to a specified dashboard.',kind:"prebuilt",parameters:[{name:"dashboard_id",type:"string",required:!0,description:"The ID of the dashboard to add the filter to, obtained from make_dashboard."},{name:"name",type:"string",required:!0,description:"A unique internal identifier for the filter. This name is used later in add_dashboard_element to bind tiles to this filter."},{name:"title",type:"string",required:!0,description:"The label displayed to users in the Looker UI."},{name:"filter_type",type:"string",required:!0,defaultValue:"field_filter",description:"The filter type of filter. Can be date_filter, number_filter, string_filter, or field_filter."},{name:"default_value",type:"string",required:!1,description:"The initial value for the filter."},{name:"model",type:"string",required:"if field_filter",description:"The name of the LookML model, obtained from get_models."},{name:"explore",type:"string",required:"if field_filter",description:"The name of the explore within the model, obtained from get_explores."},{name:"dimension",type:"string",required:"if field_filter",description:"The name of the field (e.g., view_name.field_name) to base the filter on, obtained from get_dimensions."},{name:"allow_multiple_values",type:"boolean",required:!1,defaultValue:"true",description:"The Dashboard Filter should allow multiple values"},{name:"required",type:"boolean",required:!1,defaultValue:"false",description:"The Dashboard Filter is required to run dashboard"}]},{name:"looker-conversational-analytics",type:"looker-conversational-analytics",description:'The "looker-conversational-analytics" tool will use the Conversational Analaytics API to analyze data from Looker',kind:"prebuilt"},{name:"looker-create-agent",type:"looker-create-agent",description:'"looker-create-agent" creates a Looker Conversation Analytics agent.',kind:"prebuilt"},{name:"looker-create-git-branch",type:"looker-create-git-branch",description:'A "looker-create-git-branch" tool is used to create a new git branch for a LookML project.',kind:"prebuilt"},{name:"looker-create-project-directory",type:"looker-create-project-directory",description:'A "looker-create-project-directory" tool creates a new directory in a LookML project.',kind:"prebuilt"},{name:"looker-create-project-file",type:"looker-create-project-file",description:'A "looker-create-project-file" tool creates a new LookML file in a project.',kind:"prebuilt"},{name:"looker-delete-agent",type:"looker-delete-agent",description:'"looker-delete-agent" deletes a Looker Conversation Analytics agent.',kind:"prebuilt"},{name:"looker-delete-git-branch",type:"looker-delete-git-branch",description:'A "looker-delete-git-branch" tool is used to delete a git branch of a LookML project.',kind:"prebuilt"},{name:"looker-delete-project-directory",type:"looker-delete-project-directory",description:'A "looker-delete-project-directory" tool deletes a directory from a LookML project.',kind:"prebuilt"},{name:"looker-delete-project-file",type:"looker-delete-project-file",description:'A "looker-delete-project-file" tool deletes a LookML file in a project.',kind:"prebuilt"},{name:"looker-dev-mode",type:"looker-dev-mode",description:'A "looker-dev-mode" tool changes the current session into and out of dev mode',kind:"prebuilt"},{name:"looker-generate-embed-url",type:"looker-generate-embed-url",description:'"looker-generate-embed-url" generates an embeddable URL for Looker content.',kind:"prebuilt"},{name:"looker-get-agent",type:"looker-get-agent",description:'"looker-get-agent" retrieves a Looker Conversation Analytics agent.',kind:"prebuilt"},{name:"looker-get-connection-databases",type:"looker-get-connection-databases",description:'A "looker-get-connection-databases" tool returns all the databases in a connection.',kind:"prebuilt"},{name:"looker-get-connection-schemas",type:"looker-get-connection-schemas",description:'A "looker-get-connection-schemas" tool returns all the schemas in a connection.',kind:"prebuilt"},{name:"looker-get-connection-table-columns",type:"looker-get-connection-table-columns",description:'A "looker-get-connection-table-columns" tool returns all the columns for each table specified.',kind:"prebuilt"},{name:"looker-get-connection-tables",type:"looker-get-connection-tables",description:'A "looker-get-connection-tables" tool returns all the tables in a connection.',kind:"prebuilt"},{name:"looker-get-connections",type:"looker-get-connections",description:'A "looker-get-connections" tool returns all the connections in the source.',kind:"prebuilt"},{name:"looker-get-dashboards",type:"looker-get-dashboards",description:'"looker-get-dashboards" tool searches for a saved Dashboard by name or description.',kind:"prebuilt"},{name:"looker-get-dimensions",type:"looker-get-dimensions",description:'A "looker-get-dimensions" tool returns all the dimensions from a given explore in a given model in the source.',kind:"prebuilt"},{name:"looker-get-explores",type:"looker-get-explores",description:'A "looker-get-explores" tool returns all explores for the given model from the source.',kind:"prebuilt"},{name:"looker-get-filters",type:"looker-get-filters",description:'A "looker-get-filters" tool returns all the filters from a given explore in a given model in the source.',kind:"prebuilt"},{name:"looker-get-git-branch",type:"looker-get-git-branch",description:'A "looker-get-git-branch" tool is used to retrieve the current git branch of a LookML project.',kind:"prebuilt"},{name:"looker-get-looks",type:"looker-get-looks",description:'"looker-get-looks" searches for saved Looks in a Looker source.',kind:"prebuilt"},{name:"looker-get-measures",type:"looker-get-measures",description:'A "looker-get-measures" tool returns all the measures from a given explore in a given model in the source.',kind:"prebuilt"},{name:"looker-get-models",type:"looker-get-models",description:'A "looker-get-models" tool returns all the models in the source.',kind:"prebuilt"},{name:"looker-get-parameters",type:"looker-get-parameters",description:'A "looker-get-parameters" tool returns all the parameters from a given explore in a given model in the source.',kind:"prebuilt"},{name:"looker-get-project-directories",type:"looker-get-project-directories",description:'A "looker-get-project-directories" tool returns the directories within a specific LookML project.',kind:"prebuilt"},{name:"looker-get-project-file",type:"looker-get-project-file",description:'A "looker-get-project-file" tool returns the contents of a LookML fle.',kind:"prebuilt"},{name:"looker-get-project-files",type:"looker-get-project-files",description:'A "looker-get-project-files" tool returns all the LookML fles in a project in the source.',kind:"prebuilt"},{name:"looker-get-projects",type:"looker-get-projects",description:'A "looker-get-projects" tool returns all the LookML projects in the source.',kind:"prebuilt"},{name:"looker-health-analyze",type:"looker-health-analyze",description:'"looker-health-analyze" provides a set of analytical commands for a Looker instance, allowing users to analyze projects, models, and explores.',kind:"prebuilt"},{name:"looker-health-pulse",type:"looker-health-pulse",description:'"looker-health-pulse" performs health checks on a Looker instance, with multiple actions available (e.g., checking database connections, dashboard performance, etc).',kind:"prebuilt"},{name:"looker-health-vacuum",type:"looker-health-vacuum",description:'"looker-health-vacuum" provides a set of commands to audit and identify unused LookML objects in a Looker instance.',kind:"prebuilt"},{name:"looker-list-agents",type:"looker-list-agents",description:'"looker-list-agents" retrieves the list of Looker Conversation Analytics agents.',kind:"prebuilt"},{name:"looker-list-git-branches",type:"looker-list-git-branches",description:'A "looker-list-git-branches" tool is used to retrieve the list of available git branches of a LookML project.',kind:"prebuilt"},{name:"looker-make-dashboard",type:"looker-make-dashboard",description:'"looker-make-dashboard" generates a Looker dashboard in the users personal folder in Looker',kind:"prebuilt"},{name:"looker-make-look",type:"looker-make-look",description:'"looker-make-look" generates a Looker look in the users personal folder in Looker',kind:"prebuilt"},{name:"looker-query-sql",type:"looker-query-sql",description:'"looker-query-sql" generates a sql query using the Looker semantic model.',kind:"custom"},{name:"looker-query-url",type:"looker-query-url",description:'"looker-query-url" generates a url link to a Looker explore.',kind:"prebuilt"},{name:"looker-query",type:"looker-query",description:'"looker-query" runs an inline query using the Looker semantic model.',kind:"prebuilt"},{name:"looker-run-dashboard",type:"looker-run-dashboard",description:'"looker-run-dashboard" runs the queries associated with a dashboard.',kind:"prebuilt"},{name:"looker-run-look",type:"looker-run-look",description:'"looker-run-look" runs the query associated with a saved Look.',kind:"prebuilt"},{name:"looker-switch-git-branch",type:"looker-switch-git-branch",description:'A "looker-switch-git-branch" tool is used to switch the git branch of a LookML project.',kind:"prebuilt"},{name:"looker-update-agent",type:"looker-update-agent",description:'"looker-update-agent" updates a Looker Conversation Analytics agent.',kind:"prebuilt"},{name:"looker-update-project-file",type:"looker-update-project-file",description:'A "looker-update-project-file" tool updates the content of a LookML file in a project.',kind:"prebuilt"},{name:"looker-validate-project",type:"looker-validate-project",description:'A "looker-validate-project" tool checks the syntax of a LookML project and reports any errors',kind:"prebuilt"}],customToolType:"looker-query-sql"},{slug:"mariadb",sourceType:"mysql",title:"MariaDB",description:"MariaDB is an open-source relational database compatible with MySQL.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"3306"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"queryTimeout",type:"string",required:!1,secret:!1,example:"30s",comment:"Optional: query timeout duration"}],tools:[]},{slug:"mindsdb",sourceType:"mindsdb",title:"MindsDB",description:"MindsDB is an AI federated database that enables SQL queries across hundreds of datasources and ML models.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"3306"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!1,secret:!0,example:"",comment:"Optional: omit if MindsDB is configured without authentication"},{name:"queryTimeout",type:"string",required:!1,secret:!1,example:"30s",comment:"Optional: query timeout duration"}],tools:[{name:"mindsdb-execute-sql",type:"mindsdb-execute-sql",description:'A "mindsdb-execute-sql" tool executes a SQL statement against a MindsDB federated database.',kind:"custom"},{name:"mindsdb-sql",type:"mindsdb-sql",description:'A "mindsdb-sql" tool executes a pre-defined SQL statement against a MindsDB federated database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"mindsdb-sql"},{slug:"mongodb",sourceType:"mongodb",title:"MongoDB",description:"MongoDB is a no-sql data platform that can not only serve general purpose data requirements also perform VectorSearch where both operational data and embeddings used of search can reside in same document.",fields:[{name:"uri",type:"string",required:!0,secret:!1,example:"mongodb+srv://username:password@host.mongodb.net"}],tools:[{name:"mongodb-aggregate",type:"mongodb-aggregate",description:'A "mongodb-aggregate" tool executes a multi-stage aggregation pipeline against a MongoDB collection.',kind:"prebuilt",yamlFields:["database","collection","pipelinePayload","pipelineParams","canonical","readOnly"]},{name:"mongodb-delete-many",type:"mongodb-delete-many",description:'A "mongodb-delete-many" tool deletes all documents from a MongoDB collection that match a filter.',kind:"prebuilt",yamlFields:["database","collection","filterPayload","filterParams"]},{name:"mongodb-delete-one",type:"mongodb-delete-one",description:'A "mongodb-delete-one" tool deletes a single document from a MongoDB collection.',kind:"prebuilt",yamlFields:["database","collection","filterPayload","filterParams"]},{name:"mongodb-find-one",type:"mongodb-find-one",description:'A "mongodb-find-one" tool finds and retrieves a single document from a MongoDB collection.',kind:"prebuilt",yamlFields:["database","collection","filterPayload","filterParams","projectPayload","projectParams"]},{name:"mongodb-find",type:"mongodb-find",description:'A "mongodb-find" tool finds and retrieves documents from a MongoDB collection.',kind:"prebuilt",yamlFields:["database","collection","filterPayload","filterParams","projectPayload","projectParams","sortPayload","sortParams","limit"]},{name:"mongodb-insert-many",type:"mongodb-insert-many",description:'A "mongodb-insert-many" tool inserts multiple new documents into a MongoDB collection.',kind:"prebuilt",yamlFields:["database","collection","canonical"]},{name:"mongodb-insert-one",type:"mongodb-insert-one",description:'A "mongodb-insert-one" tool inserts a single new document into a MongoDB collection.',kind:"prebuilt",yamlFields:["database","collection","canonical"]},{name:"mongodb-update-many",type:"mongodb-update-many",description:'A "mongodb-update-many" tool updates all documents in a MongoDB collection that match a filter.',kind:"prebuilt",yamlFields:["database","collection","filterPayload","filterParams","updatePayload","updateParams","canonical","upsert"]},{name:"mongodb-update-one",type:"mongodb-update-one",description:'A "mongodb-update-one" tool updates a single document in a MongoDB collection.',kind:"prebuilt",yamlFields:["database","collection","filterPayload","filterParams","updatePayload","updateParams","canonical","upsert"]}]},{slug:"mssql",sourceType:"mssql",title:"SQL Server",description:"SQL Server is a relational database management system (RDBMS).",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"1433"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[{name:"mssql-execute-sql",type:"mssql-execute-sql",description:'A "mssql-execute-sql" tool executes a SQL statement against a SQL Server database.',kind:"custom"},{name:"mssql-list-tables",type:"mssql-list-tables",description:'The "mssql-list-tables" tool lists schema information for all or specified tables in a SQL server database.',kind:"prebuilt"},{name:"mssql-sql",type:"mssql-sql",description:'A "mssql-sql" tool executes a pre-defined SQL statement against a SQL Server database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"mssql-sql"},{slug:"mysql",sourceType:"mysql",title:"MySQL",description:"MySQL is a relational database management system that stores and manages data.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"3306"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"queryTimeout",type:"string",required:!1,secret:!1,example:"30s",comment:"Optional: query timeout duration"}],tools:[{name:"mysql-execute-sql",type:"mysql-execute-sql",description:'A "mysql-execute-sql" tool executes a SQL statement against a MySQL database.',kind:"custom"},{name:"mysql-get-query-plan",type:"mysql-get-query-plan",description:'A "mysql-get-query-plan" tool gets the execution plan for a SQL statement against a MySQL database.',kind:"prebuilt"},{name:"mysql-list-active-queries",type:"mysql-list-active-queries",description:'A "mysql-list-active-queries" tool lists active queries in a MySQL database.',kind:"prebuilt"},{name:"mysql-list-table-fragmentation",type:"mysql-list-table-fragmentation",description:'A "mysql-list-table-fragmentation" tool lists top N fragemented tables in MySQL.',kind:"prebuilt"},{name:"mysql-list-table-stats",type:"mysql-list-table-stats",description:'A "mysql-list-table-stats" tool report table statistics including table size, total latency, rows read, rows written, read and write latency for entire instance, a specified database, or a specified table.',kind:"prebuilt"},{name:"mysql-list-tables-missing-unique-indexes",type:"mysql-list-tables-missing-unique-indexes",description:'A "mysql-list-tables-missing-unique-indexes" tool lists tables that do not have primary or unique indices in a MySQL instance.',kind:"prebuilt"},{name:"mysql-list-tables",type:"mysql-list-tables",description:'The "mysql-list-tables" tool lists schema information for all or specified tables in a MySQL database.',kind:"prebuilt"},{name:"mysql-sql",type:"mysql-sql",description:'A "mysql-sql" tool executes a pre-defined SQL statement against a MySQL database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"mysql-sql"},{slug:"neo4j",sourceType:"neo4j",title:"Neo4j",description:"Neo4j is a powerful, open source graph database system",fields:[{name:"uri",type:"string",required:!0,secret:!1,example:"neo4j+s://xxxx.databases.neo4j.io:7687"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"database",type:"string",required:!0,secret:!1,example:"neo4j"}],tools:[{name:"neo4j-cypher",type:"neo4j-cypher",description:'A "neo4j-cypher" tool executes a pre-defined cypher statement against a Neo4j database.',kind:"custom",yamlFields:["statement","parameters"]},{name:"neo4j-execute-cypher",type:"neo4j-execute-cypher",description:'A "neo4j-execute-cypher" tool executes any arbitrary Cypher statement against a Neo4j database.',kind:"prebuilt",yamlFields:["readOnly"]},{name:"neo4j-schema",type:"neo4j-schema",description:'A "neo4j-schema" tool extracts a comprehensive schema from a Neo4j database.',kind:"prebuilt",yamlFields:["cacheExpireMinutes"]}],customToolType:"neo4j-cypher"},{slug:"oceanbase",sourceType:"oceanbase",title:"OceanBase",description:"OceanBase is a distributed relational database that provides high availability, scalability, and compatibility with MySQL.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"2881"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"queryTimeout",type:"string",required:!1,secret:!1,example:"30s",comment:"Optional: query timeout duration"}],tools:[{name:"oceanbase-execute-sql",type:"oceanbase-execute-sql",description:'An "oceanbase-execute-sql" tool executes a SQL statement against an OceanBase database.',kind:"custom"},{name:"oceanbase-sql",type:"oceanbase-sql",description:'An "oceanbase-sql" tool executes a pre-defined SQL statement against an OceanBase database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"oceanbase-sql"},{slug:"oracle",sourceType:"oracle",title:"Oracle",description:"Oracle Database is a widely-used relational database management system.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"1521"},{name:"serviceName",type:"string",required:!0,secret:!1,example:"XEPDB1"},{name:"connectionString",type:"string",required:!0,secret:!1,example:"127.0.0.1:1521/XEPDB1"},{name:"tnsAlias",type:"string",required:!0,secret:!1,example:"MY_DB_ALIAS"},{name:"tnsAdmin",type:"string",required:!1,secret:!1,example:"/opt/oracle/network/admin",comment:"Optional: overrides TNS_ADMIN env var"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[{name:"oracle-execute-sql",type:"oracle-execute-sql",description:'An "oracle-execute-sql" tool executes a SQL statement against an Oracle database.',kind:"custom"},{name:"oracle-list-tables",type:"oracle-list-tables",description:"Lists all tables in the current user's schema",kind:"prebuilt"},{name:"oracle-sql",type:"oracle-sql",description:'An "oracle-sql" tool executes a pre-defined SQL statement against an Oracle database.',kind:"custom"}],customToolType:"oracle-sql"},{slug:"postgres",sourceType:"postgres",title:"PostgreSQL",description:"PostgreSQL is a powerful, open source object-relational database.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"5432"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[{name:"postgres-database-overview",type:"postgres-database-overview",description:'The "postgres-database-overview" fetches the current state of the PostgreSQL server.',kind:"prebuilt"},{name:"postgres-execute-sql",type:"postgres-execute-sql",description:'A "postgres-execute-sql" tool executes a SQL statement against a Postgres database.',kind:"custom"},{name:"postgres-get-column-cardinality",type:"postgres-get-column-cardinality",description:'The "postgres-get-column-cardinality" tool estimates the number of unique values in one or all columns of a Postgres database table.',kind:"prebuilt"},{name:"postgres-list-active-queries",type:"postgres-list-active-queries",description:'The "postgres-list-active-queries" tool lists currently active queries in a Postgres database.',kind:"prebuilt"},{name:"postgres-list-available-extensions",type:"postgres-list-available-extensions",description:'The "postgres-list-available-extensions" tool retrieves all PostgreSQL extensions available for installation on a Postgres database.',kind:"prebuilt",yamlFields:["address_standardizer","amcheck","anon","autoinc"]},{name:"postgres-list-database-stats",type:"postgres-list-database-stats",description:'The "postgres-list-database-stats" tool lists lists key performance and activity statistics of PostgreSQL databases.',kind:"prebuilt"},{name:"postgres-list-indexes",type:"postgres-list-indexes",description:'The "postgres-list-indexes" tool lists indexes in a Postgres database.',kind:"prebuilt"},{name:"postgres-list-installed-extensions",type:"postgres-list-installed-extensions",description:'The "postgres-list-installed-extensions" tool retrieves all PostgreSQL extensions installed on a Postgres database.',kind:"prebuilt"},{name:"postgres-list-locks",type:"postgres-list-locks",description:'The "postgres-list-locks" tool lists active locks in the database, including the associated process, lock type, relation, mode, and the query holding or waiting on the lock.',kind:"prebuilt",yamlFields:["pid","usename","query","trxid","locks"]},{name:"postgres-list-pg-settings",type:"postgres-list-pg-settings",description:'The "postgres-list-pg-settings" tool lists PostgreSQL run-time configuration settings.',kind:"prebuilt"},{name:"postgres-list-publication-tables",type:"postgres-list-publication-tables",description:'The "postgres-list-publication-tables" tool lists publication tables in a Postgres database.',kind:"prebuilt"},{name:"postgres-list-query-stats",type:"postgres-list-query-stats",description:'The "postgres-list-query-stats" tool lists query statistics from a Postgres database.',kind:"prebuilt"},{name:"postgres-list-roles",type:"postgres-list-roles",description:'The "postgres-list-roles" tool lists user-created roles in a Postgres database.',kind:"prebuilt"},{name:"postgres-list-schemas",type:"postgres-list-schemas",description:'The "postgres-list-schemas" tool lists user-defined schemas in a database.',kind:"prebuilt"},{name:"postgres-list-sequences",type:"postgres-list-sequences",description:'The "postgres-list-sequences" tool lists sequences in a Postgres database.',kind:"prebuilt"},{name:"postgres-list-stored-procedure",type:"postgres-list-stored-procedure",description:'The "postgres-list-stored-procedure" tool retrieves metadata for stored procedures in PostgreSQL, including procedure definitions, owners, languages, and descriptions.',kind:"prebuilt",parameters:[{name:"role_name",type:"string",required:!1,defaultValue:"null",description:"Optional: The owner name to filter stored procedures by (supports partial matching)"},{name:"schema_name",type:"string",required:!1,defaultValue:"null",description:"Optional: The schema name to filter stored procedures by (supports partial matching)"},{name:"limit",type:"integer",required:!1,defaultValue:"20",description:"Optional: The maximum number of stored procedures to return"}]},{name:"postgres-list-table-stats",type:"postgres-list-table-stats",description:'The "postgres-list-table-stats" tool reports table statistics including size, scan metrics, and bloat indicators for PostgreSQL tables.',kind:"prebuilt",parameters:[{name:"schema_name",type:"string",required:!1,defaultValue:'"public"',description:"Optional: A specific schema name to filter by (supports partial matching)"},{name:"table_name",type:"string",required:!1,defaultValue:"null",description:"Optional: A specific table name to filter by (supports partial matching)"},{name:"owner",type:"string",required:!1,defaultValue:"null",description:"Optional: A specific owner to filter by (supports partial matching)"},{name:"sort_by",type:"string",required:!1,defaultValue:"null",description:"Optional: The column to sort by. Valid values: size, dead_rows, seq_scan, idx_scan (defaults to seq_scan)"},{name:"limit",type:"integer",required:!1,defaultValue:"50",description:"Optional: The maximum number of results to return"}]},{name:"postgres-list-tables",type:"postgres-list-tables",description:'The "postgres-list-tables" tool lists schema information for all or specified tables in a Postgres database.',kind:"prebuilt"},{name:"postgres-list-tablespaces",type:"postgres-list-tablespaces",description:'The "postgres-list-tablespaces" tool lists tablespaces in a Postgres database.',kind:"prebuilt"},{name:"postgres-list-triggers",type:"postgres-list-triggers",description:'The "postgres-list-triggers" tool lists triggers in a Postgres database.',kind:"prebuilt"},{name:"postgres-list-views",type:"postgres-list-views",description:'The "postgres-list-views" tool lists views in a Postgres database, with a default limit of 50 rows.',kind:"prebuilt"},{name:"postgres-long-running-transactions",type:"postgres-long-running-transactions",description:"The postgres-long-running-transactions tool Identifies and lists database transactions that exceed a specified time limit. For each of the long running transactions, the output contains the process id, database name, user name, application name, client address, state, connection age, transaction age, query age, last activity age, wait event type, wait event, and query string.",kind:"prebuilt"},{name:"postgres-replication-stats",type:"postgres-replication-stats",description:'The "postgres-replication-stats" tool reports replication-related metrics for WAL streaming replicas, including lag sizes presented in human-readable form.',kind:"prebuilt",yamlFields:["pid","usename","application_name","backend_xmin","client_addr","state","sync_state","sent_lag","write_lag","flush_lag","replay_lag","total_lag"]},{name:"postgres-sql",type:"postgres-sql",description:'A "postgres-sql" tool executes a pre-defined SQL statement against a Postgres database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"postgres-sql"},{slug:"redis",sourceType:"redis",title:"Redis",description:"Redis is a in-memory data structure store.",fields:[{name:"address",type:"string",required:!0,secret:!1,example:""},{name:"username",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:"",comment:"Omit this field if you don't have a password."}],tools:[{name:"redis-tool",type:"redis",description:'A "redis" tool executes a set of pre-defined Redis commands against a Redis instance.',kind:"custom",yamlFields:["commands","parameters"]}],customToolType:"redis",customToolShape:"commands"},{slug:"serverless-spark",sourceType:"serverless-spark",title:"Serverless for Apache Spark",description:"Google Cloud Serverless for Apache Spark lets you run Spark workloads without requiring you to provision and manage your own Spark cluster.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"location",type:"string",required:!0,secret:!1,example:"us-central1"}],tools:[{name:"serverless-spark-cancel-batch",type:"serverless-spark-cancel-batch",description:'A "serverless-spark-cancel-batch" tool cancels a running Spark batch operation.',kind:"prebuilt",hasAuthRequired:!0},{name:"serverless-spark-create-pyspark-batch",type:"serverless-spark-create-pyspark-batch",description:'A "serverless-spark-create-pyspark-batch" tool submits a Spark batch to run asynchronously.',kind:"prebuilt",yamlFields:["runtimeConfig","environmentConfig"],hasAuthRequired:!0},{name:"serverless-spark-create-spark-batch",type:'"serverless-spark-create-spark-batch"',description:'A "serverless-spark-create-spark-batch" tool submits a Spark batch to run asynchronously.',kind:"prebuilt",yamlFields:["runtimeConfig","environmentConfig"],hasAuthRequired:!0},{name:"serverless-spark-get-batch",type:"serverless-spark-get-batch",description:'A "serverless-spark-get-batch" tool gets a single Spark batch from the source.',kind:"prebuilt",hasAuthRequired:!0},{name:"serverless-spark-get-session-template",type:"serverless-spark-get-session-template",description:'A "serverless-spark-get-session-template" tool retrieves a specific Spark session template from the source.',kind:"prebuilt",hasAuthRequired:!0},{name:"serverless-spark-list-batches",type:"serverless-spark-list-batches",description:'A "serverless-spark-list-batches" tool returns a list of Spark batches from the source.',kind:"prebuilt",hasAuthRequired:!0}]},{slug:"singlestore",sourceType:"singlestore",title:"SingleStore",description:"SingleStore is the cloud-native database built with speed and scale to power data-intensive applications.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"3306"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"queryTimeout",type:"string",required:!1,secret:!1,example:"30s",comment:"Optional: query timeout duration"}],tools:[{name:"singlestore-execute-sql",type:"singlestore-execute-sql",description:'A "singlestore-execute-sql" tool executes a SQL statement against a SingleStore database.',kind:"custom"},{name:"singlestore-sql",type:"singlestore-sql",description:'A "singlestore-sql" tool executes a pre-defined SQL statement against a SingleStore database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"singlestore-sql"},{slug:"snowflake",sourceType:"snowflake",title:"Snowflake",description:"Snowflake is a cloud-based data platform.",fields:[{name:"account",type:"string",required:!0,secret:!1,example:""},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"database",type:"string",required:!0,secret:!1,example:""},{name:"schema",type:"string",required:!0,secret:!1,example:""},{name:"warehouse",type:"string",required:!0,secret:!1,example:""},{name:"role",type:"string",required:!0,secret:!1,example:""}],tools:[{name:"snowflake-execute-sql",type:"snowflake-execute-sql",description:'A "snowflake-execute-sql" tool executes a SQL statement against a Snowflake database.',kind:"custom",hasAuthRequired:!0},{name:"snowflake-sql",type:"snowflake-sql",description:'A "snowflake-sql" tool executes a pre-defined SQL statement against a Snowflake database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"],hasAuthRequired:!0}],customToolType:"snowflake-sql"},{slug:"spanner",sourceType:"spanner",title:"Spanner",description:"Spanner is a fully managed database service from Google Cloud that combines relational, key-value, graph, and search capabilities.",fields:[{name:"project",type:"string",required:!0,secret:!1,example:"my-project-id"},{name:"instance",type:"string",required:!0,secret:!1,example:"my-instance"},{name:"database",type:"string",required:!0,secret:!1,example:"my_db"}],tools:[{name:"spanner-execute-sql",type:"spanner-execute-sql",description:'A "spanner-execute-sql" tool executes a SQL statement against a Spanner database.',kind:"custom",yamlFields:["readOnly"]},{name:"spanner-list-graphs",type:"spanner",description:'A "spanner-list-graphs" tool retrieves schema information about graphs in a Google Cloud Spanner database.',kind:"prebuilt",parameters:[{name:"graph_names",type:"string",required:!1,defaultValue:'""',description:"Comma-separated list of graph names to filter. If empty, lists all graphs in user-accessible schemas"},{name:"output_format",type:"string",required:!1,defaultValue:'"detailed"',description:'Output format: "simple" returns only graph names, "detailed" returns full schema information'}],hasAuthRequired:!0},{name:"spanner-list-tables",type:"spanner",description:'A "spanner-list-tables" tool retrieves schema information about tables in a Google Cloud Spanner database.',kind:"prebuilt",parameters:[{name:"table_names",type:"string",required:!1,defaultValue:'""',description:"Comma-separated list of table names to filter. If empty, lists all tables in user-accessible schemas"},{name:"output_format",type:"string",required:!1,defaultValue:'"detailed"',description:'Output format: "simple" returns only table names, "detailed" returns full schema information'}],hasAuthRequired:!0},{name:"spanner-sql",type:"spanner-sql",description:'A "spanner-sql" tool executes a pre-defined SQL statement against a Google Cloud Spanner database.',kind:"custom",yamlFields:["statement","parameters","readOnly","templateParameters"]}],customToolType:"spanner-sql"},{slug:"sqlite",sourceType:"sqlite",title:"SQLite",description:"SQLite is a C-language library that implements a small, fast, self-contained, high-reliability, full-featured, SQL database engine.",fields:[{name:"database",type:"string",required:!0,secret:!1,example:"/path/to/database.db"}],tools:[{name:"sqlite-execute-sql",type:"sqlite-execute-sql",description:'A "sqlite-execute-sql" tool executes a single SQL statement against a SQLite database.',kind:"custom"},{name:"sqlite-sql",type:"sqlite-sql",description:"Execute SQL statements against a SQLite database.",kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"sqlite-sql"},{slug:"tidb",sourceType:"tidb",title:"TiDB",description:"TiDB is a distributed SQL database that combines the best of traditional RDBMS and NoSQL databases.",fields:[],tools:[{name:"tidb-execute-sql",type:"tidb-execute-sql",description:'A "tidb-execute-sql" tool executes a SQL statement against a TiDB database.',kind:"custom"},{name:"tidb-sql",type:"tidb-sql",description:'A "tidb-sql" tool executes a pre-defined SQL statement against a TiDB database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"tidb-sql"},{slug:"trino",sourceType:"trino",title:"Trino",description:"Trino is a distributed SQL query engine for big data analytics.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"trino.example.com"},{name:"port",type:"number",required:!0,secret:!1,example:"8080"},{name:"user",type:"string",required:!1,secret:!1,example:"",comment:"Optional for anonymous access"},{name:"password",type:"string",required:!1,secret:!0,example:"",comment:"Optional"},{name:"catalog",type:"string",required:!0,secret:!1,example:"hive"},{name:"schema",type:"string",required:!0,secret:!1,example:"default"}],tools:[{name:"trino-execute-sql",type:"trino-execute-sql",description:'A "trino-execute-sql" tool executes a SQL statement against a Trino database.',kind:"custom"},{name:"trino-sql",type:"trino-sql",description:'A "trino-sql" tool executes a pre-defined SQL statement against a Trino database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"trino-sql"},{slug:"valkey",sourceType:"valkey",title:"Valkey",description:"Valkey is an open-source, in-memory data structure store, forked from Redis.",fields:[{name:"address",type:"string",required:!0,secret:!1,example:""},{name:"username",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""}],tools:[{name:"valkey-tool",type:"valkey",description:'A "valkey" tool executes a set of pre-defined Valkey commands against a Valkey instance.',kind:"prebuilt"}]},{slug:"yuagbytedb",sourceType:"yugabytedb",title:"YugabyteDB",description:"YugabyteDB is a high-performance, distributed SQL database.",fields:[{name:"host",type:"string",required:!0,secret:!1,example:"127.0.0.1"},{name:"port",type:"number",required:!0,secret:!1,example:"5433"},{name:"database",type:"string",required:!0,secret:!1,example:"yugabyte"},{name:"user",type:"string",required:!0,secret:!1,example:""},{name:"password",type:"string",required:!0,secret:!0,example:""},{name:"loadBalance",type:"boolean",required:!0,secret:!1,example:"true"},{name:"topologyKeys",type:"string",required:!0,secret:!1,example:"cloud.region.zone1:1,cloud.region.zone2:2"}],tools:[{name:"yugabytedb-sql",type:"yugabytedb-sql",description:'A "yugabytedb-sql" tool executes a pre-defined SQL statement against a YugabyteDB database.',kind:"custom",yamlFields:["statement","parameters","templateParameters"]}],customToolType:"yugabytedb-sql"}];function a(t){return r.find(e=>e.slug===t)||r.find(e=>e.sourceType===t)}export{r as TOOLBOX_CATALOG,a as getToolboxIntegration};
@@ -0,0 +1,2 @@
1
+ import"dotenv/config";import g from"express";import d from"path";import p from"fs";import T from"compression";import{fileURLToPath as J}from"url";import R from"body-parser";import Y from"https";import Q from"jsonwebtoken";import Z from"node:crypto";import{WebSocketServer as q}from"ws";import{verifyToken as ee,isUsernameExists as oe,activateUser as te}from"./services/auth";import{isApiKeyActive as se}from"./core/services/api-keys-service";import{config as x}from"./core/config";import{BRAND_NAME as A}from"./core/app-config/branding";import{defineUnprotectedRoutes as re,defineProtectedRoutes as ne}from"./routes";import{attachHandlers as ae}from"./ws/handler";import ie from"./routes/pdf";import ce from"./routes/proxy-logos";import{logger as le,logRequest as de}from"./core/utils/logger";import{initializeChatTracesIndex as ue}from"./core/services/chat-traces-service";import{initializeMemoriesIndex as pe}from"./core/services/memories-service";import{initializeAssistantsIndex as me}from"./core/services/assistants-index-service";import{ensureAlertsIndex as ge}from"./core/services/alerts-service";import{startAlertScheduler as fe}from"./services/alert-evaluator";import{initializeToolMetricsIndex as he,startToolMetricsScheduler as ve}from"./core/services/tool-metrics-service";import{initializeGoldenQuestionsIndex as ke}from"./core/services/golden-questions-service";import{initializeToolHistoryIndex as ye}from"./core/services/tool-history-service";import{driverManager as P}from"./core/services/asyncapi-drivers/driver-manager";import{getShareLinkById as Se,frameAncestorsValue as we}from"./core/services/share-service";import"elastic-apm-node/start";process.on("uncaughtException",t=>{console.error("\u274C Uncaught Exception:",t),process.exit(1)}),process.on("unhandledRejection",(t,m)=>{console.error("\u274C Unhandled Rejection at:",m,"reason:",t)});const y=d.dirname(J(import.meta.url)),f=d.resolve(y,".."),ao=p.createWriteStream(y+"/log/access.log",{flags:"a"}),S=parseInt(process.env.PORT||"3003");process.env.NODE_TLS_REJECT_UNAUTHORIZED="0";var be=x.jwtSecret,Te=x.issuer;async function Re(){le.info("Starting stkxp-app server...");const t=g(),m=process.env.NODE_ENV==="production",h=m?null:await(async()=>{const{createServer:o}=await import("vite");return o({root:f,server:{middlewareMode:!0,hmr:{port:24678,protocol:"wss",host:"51.158.76.76",overlay:!1}},appType:"custom"})})();t.use(T({level:6,threshold:1024,filter:(o,e)=>o.headers["cache-control"]?.includes("no-transform")?!1:T.filter(o,e)}));{const{stripeWebhookHandler:o}=await import("./routes/billing-routes");t.post("/buy-subscription",g.raw({type:"application/json"}),o),console.log("\u2713 Stripe webhook registered at /buy-subscription")}{const{mountTeamMcpRoutes:o}=await import("./routes/mcp-team-routes");o(t),console.log("\u2713 Team MCP routes registered at /api/mcp/team/:teamId")}t.use(R.json({limit:"50mb"})),t.use(R.urlencoded({limit:"50mb",extended:!1,parameterLimit:5e4})),t.use((o,e,n)=>{o.body==null&&(o.body={}),n()}),t.use((o,e,n)=>{const s=o.headers.cookie||"";o.cookies=s.split(";").reduce((r,a)=>{const i=a.indexOf("=");if(i>0){const c=a.slice(0,i).trim(),l=a.slice(i+1).trim();try{r[c]=decodeURIComponent(l)}catch{r[c]=l}}return r},{}),n()}),t.use((o,e,n)=>{const s=Date.now();e.on("finish",()=>{const r=Date.now()-s;de(o,e,r)}),n()}),t.use((o,e,n)=>{if(e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, X-USER-ID, Authorization"),e.setHeader("X-Content-Type-Options","nosniff"),o.path.startsWith("/embed")||e.setHeader("X-Frame-Options","SAMEORIGIN"),o.path==="/embed.js"||o.path.startsWith("/embed/")?e.setHeader("Cache-Control","no-cache, must-revalidate"):o.url.match(/\.(js|css|woff2?|ttf|svg|png|jpg|jpeg|gif|ico)$/)?e.setHeader("Cache-Control","public, max-age=31536000, immutable"):(o.url==="/"||o.url==="/index.html")&&e.setHeader("Cache-Control","no-cache, must-revalidate"),o.method==="OPTIONS")return e.sendStatus(200);n()}),t.use((o,e,n)=>{n()}),console.log("\u2192 Loading public packages router...");const{publicRouter:H}=await import("./routes/packages");t.use("/public/packages",H),console.log("\u2713 Public packages routes loaded"),t.use(g.static(d.resolve(f,"public")));const{serveIntegrationLogoFallback:E}=await import("./middleware/integration-logos");t.use(E),t.use("/verify-email",async(o,e,n)=>{const s=o.query.emailToken,r=o.query.username;if(typeof s!="string"||typeof r!="string"||!s||!r)return e.status(400).json({status:"Failed",error:"empty request"});const a=await oe(r),i=a?.body?.[r]??a?.[r];if(!i)return e.status(404).json({status:"Failed",error:"User not found"});const c=i?.metadata?.emailToken;if(!c)return e.status(410).json({status:"Failed",error:"Activation already used or unavailable"});const l=Buffer.from(c),k=Buffer.from(s);return l.length!==k.length||!Z.timingSafeEqual(l,k)?(console.warn(`[verify-email] Bad activation token for ${r} from ${o.ip}`),e.status(401).json({status:"Failed",error:"Invalid activation token"})):(await te(r),console.log(`[verify-email] Activated ${r} via token`),e.redirect("/login"))}),t.use(ce),t.use((o,e,n)=>{if(o.path==="/api/stack_expert/chats"||o.path.startsWith("/api/stack_expert/chats/")){const s=o.originalUrl.replace("/api/stack_expert/chats","/api/chats");return e.redirect(308,s)}if(o.path.startsWith("/api/stack_expert/auth/")){const s=o.originalUrl.replace("/api/stack_expert/auth","/api/auth");return e.redirect(308,s)}n()}),re(t),console.log("\u2192 Mounting OpenAPI docs...");const{buildOpenApiDocument:I}=await import("./openapi/generator"),w=await import("swagger-ui-express");t.get("/api/openapi.json",(o,e)=>{const n=o.query.audience==="internal"?"internal":"public",{doc:s}=I({audience:n});e.json(s)}),t.use("/api/docs",w.serve,w.setup(void 0,{explorer:!1,swaggerOptions:{url:"/api/openapi.json"},customSiteTitle:`${A} API docs`})),console.log("\u2713 OpenAPI docs mounted at /api/docs (spec: /api/openapi.json)");const{buildAsyncApiDocument:C}=await import("./asyncapi/generator");t.get("/api/asyncapi.json",(o,e)=>{const{doc:n}=C();e.json(n)}),t.get("/api/asyncapi-docs",(o,e)=>{const n=d.resolve(y,"asyncapi/viewer.html");try{const r=p.readFileSync(n,"utf8").replace(/Stack Expert/g,A);e.setHeader("Content-Type","text/html; charset=utf-8"),e.send(r)}catch{e.sendFile(n)}}),console.log("\u2713 AsyncAPI docs mounted at /api/asyncapi-docs (spec: /api/asyncapi.json)");const{HTML_TOOL_OPENAPI_SPEC:L}=await import("./openapi/html-tool-spec");t.get("/api/html/openapi.json",(o,e)=>{e.json(L)}),console.log("\u2713 Chat-to-HTML tool spec mounted at /api/html/openapi.json"),t.use("/api/",async(o,e,n)=>{var s=o?.headers.authorization;if(!s){const r=o?.headers["x-api-key"],a=Array.isArray(r)?r[0]:r;a&&(s=`Bearer ${a}`)}if(s)ee(o,s,async function(r,a){if(r){if(console.log("Token verification error:----"),!e.headersSent)return e.status(401).json({success:!1,message:"Failed to authenticate token."})}else{if(a?.type==="apikey")try{if(!await se(a.username,a.jti))return e.headersSent?void 0:e.status(401).json({success:!1,message:"API key has been revoked."})}catch(i){return console.error("[auth] API key revocation check failed:",i),e.headersSent?void 0:e.status(401).json({success:!1,message:"Failed to validate API key."})}n()}});else return e.status(401).json({success:!1,message:"No token provided."})}),ne(t),console.log("\u2713 Protected routes defined"),t.use("/api/pdf",ie),console.log("\u2713 PDF routes loaded");const _=(await import("./routes/html-routes")).default;t.use("/api/html",_),console.log("\u2713 HTML export routes loaded");const j=(await import("./routes/transcribe-routes")).default;t.use("/api",j),console.log("\u2713 Transcribe route loaded"),console.log("\u2192 Loading packages router...");const O=(await import("./routes/packages")).default;t.use("/api/stack_expert/settings/packages",O),console.log("\u2713 Packages routes loaded"),console.log("\u2192 Loading platforms router...");const M=(await import("./routes/platforms-routes")).default;t.use("/api/stack_expert",M),console.log("\u2713 Platforms routes loaded"),console.log("\u2192 Loading toolbox import router...");const W=(await import("./routes/toolbox-import-routes")).default;t.use("/api/import",W),console.log("\u2713 Toolbox import routes loaded"),console.log("\u2192 Loading sources routers...");const U=(await import("./routes/sources-catalog-routes")).default;t.use("/api/sources",U);const F=(await import("./routes/sources-routes")).default;t.use("/api/sources",F),console.log("\u2713 Sources routes loaded"),console.log("\u2192 Loading integrations router...");const N=(await import("./routes/integrations-routes")).default;t.use("/api/stack_expert/integrations",N),console.log("\u2713 Integrations routes loaded"),console.log("\u2192 Loading compare router...");const D=(await import("./routes/compare")).default;t.use("/api/stack_expert/compare",D),console.log("\u2713 Compare routes loaded"),console.log("\u2192 Loading A2A routes...");const V=(await import("./routes/a2a-routes")).default;t.use("/api/stack_expert",V),console.log("\u2713 A2A routes loaded"),console.log("\u2192 Loading connectors routes...");const $=(await import("./routes/connectors-routes")).default;t.use("/api/stack_expert",$),console.log("\u2713 Connectors routes loaded"),console.log("\u2192 Loading elastic tool execution routes...");const z=(await import("./routes/elastic-tool-execution-routes")).default;if(t.use("/api/stack_expert",z),console.log("\u2713 Elastic tool execution routes loaded"),t.get("/embed/:linkId",async(o,e,n)=>{try{const s=await Se(o.params.linkId),r=s&&s.embed?we(s.allowedOrigins):"'none'";e.removeHeader("X-Frame-Options"),e.setHeader("Content-Security-Policy",`frame-ancestors ${r}`)}catch{e.removeHeader("X-Frame-Options"),e.setHeader("Content-Security-Policy","frame-ancestors 'none'")}n()}),console.log("\u2713 Embed widget document route configured"),m){console.log("\u2192 Serving pre-built frontend from dist/ (production)...");const o=d.resolve(f,"dist"),e=d.resolve(o,"index.html");t.use(g.static(o)),t.use("/",(n,s,r)=>{const a=n.originalUrl.split("?")[0];if(/\.[^/]+$/.test(a)&&!a.endsWith(".html"))return r();try{s.status(200).set({"Content-Type":"text/html"}).end(p.readFileSync(e,"utf-8"))}catch(i){r(i)}}),console.log("\u2713 Static frontend handler configured (production)")}else console.log("\u2192 Loading Vite middlewares (development)..."),t.use(h.middlewares),console.log("\u2713 Vite middlewares loaded"),console.log("\u2192 Setting up HTML handler..."),t.use("/",async(o,e,n)=>{const s=o.originalUrl;if(/\.[^/]+$/.test(s.split("?")[0])&&!s.split("?")[0].endsWith(".html"))return n();try{const r=d.resolve(f,"index.html");let a=p.readFileSync(r,"utf-8");a=await h.transformIndexHtml(s,a),e.status(200).set({"Content-Type":"text/html"}).end(a)}catch(r){h.ssrFixStacktrace(r),n(r)}}),console.log("\u2713 HTML handler configured (development)");console.log("\u2192 Loading SSL certificates...");const B=process.env.SSL_KEY_PATH||"/root/docker/diagnostics/certificates/kib012/kib012.key",G=process.env.SSL_CERT_PATH||"/root/docker/diagnostics/certificates/kib012/kib012.crt",K=p.readFileSync(B,"utf8"),X=p.readFileSync(G,"utf8");console.log("\u2713 SSL certificates loaded"),console.log("\u2192 Creating HTTPS server...");const u=Y.createServer({key:K,cert:X},t);console.log("\u2713 HTTPS server created"),console.log("\u2192 Creating WebSocket server...");const v=new q({server:u,verifyClient:(o,e)=>{if(console.log("WebSocket verifyClient called"),o.req.headers["sec-websocket-protocol"]==="vite-hmr")return console.log("[WebSocket] Accepting Vite HMR connection"),e(!0);const r=new URLSearchParams(o.req.url.split("?")[1]).get("token");if(r){var a=r;Q.verify(a,be,function(i,c){if(i==null&&c){var l=c.iss==Te;l?e(!0):e(!1,403,"Access Denied: Invalid issuer")}else e(!1,403,"Access Denied: Invalid token")})}else e(!1,403,"Access Denied: No token provided")},path:"/"});console.log("\u2713 WebSocket server created"),console.log("\u2192 Attaching WebSocket connection handler..."),v.on("connection",(o,e)=>{if(console.log("[SERVER] \u{1F50C} New WebSocket connection attempt"),e.headers["sec-websocket-protocol"]==="vite-hmr"){console.log("[SERVER] Vite HMR client connected - skipping chat handlers");return}let s=new URLSearchParams(e.url.split("?")[1]);console.log("[SERVER] WebSocket connection established",s.toString());let r=s.get("token")??"";const a=s.get("shareToken")??void 0;return r||((e.headers.cookie??"").split(";").forEach(c=>{const l=c.indexOf("=");if(l>0&&c.slice(0,l).trim()==="guestToken")try{r=decodeURIComponent(c.slice(l+1).trim())}catch{r=c.slice(l+1).trim()}}),r&&console.log("[SERVER] Using guestToken cookie for WS auth")),console.log("[SERVER] Token present:",r?`Yes (${r.substring(0,30)}...)`:"No"),a&&console.log("[SERVER] shareToken present:",a),ae(o,r,a)}),console.log("\u2713 WebSocket connection handler attached"),console.log("\u2192 Starting HTTPS server on port 3003...");const b=()=>{console.log(`
2
+ \u{1F504} Graceful shutdown initiated...`),P.shutdown().catch(o=>console.warn(`[asyncapi-drivers] shutdown error: ${o?.message??o}`)),v.clients.forEach(o=>{o.close(1e3,"Server shutting down")}),v.close(()=>{console.log("\u{1F4E1} WebSocket server closed")}),u.close(()=>{console.log("\u{1F510} HTTPS server closed"),console.log("\u2705 Server shutdown complete"),process.exit(0)}),setTimeout(()=>{},1e4)};return process.on("SIGINT",b),process.on("SIGTERM",b),new Promise((o,e)=>{u.once("listening",()=>{const n=u.address();console.log("\u2705 Server 'listening' event fired!"),console.log("\u2705 Server address:",n),console.log("\u2705 App running on https://localhost:3003"),console.log(`\u2705 WS server running on wss://localhost:${S}`),console.log("\u2705 Server startup completed successfully"),ue().catch(()=>{}),pe().catch(()=>{}),me().catch(()=>{}),ge().then(()=>fe()).catch(s=>console.error("[alerts] boot failed:",s)),he().then(()=>ve()).catch(s=>console.error("[tool-metrics] boot failed:",s)),ke().catch(s=>console.error("[golden-questions] boot failed:",s)),ye().catch(s=>console.error("[tool-history] boot failed:",s)),P.bootstrapAllPlatformSubscribers().catch(s=>console.error("[asyncapi-drivers] bootstrap failed:",s)),o()}),u.once("error",n=>{console.error("\u274C Server listen error:",n.message,n.code),e(n)}),setTimeout(()=>{try{const n=process.env.HOST||"127.0.0.1";console.log("\u2713 Calling server.listen() on port",S,"host:",n),u.listen(S,n,()=>{console.log("\u2713 server.listen() callback invoked")}),console.log("\u2713 server.listen() called, waiting for events...")}catch(n){console.error("\u274C Synchronous exception in server.listen():",n),e(n)}},100)})}Re().catch(t=>{console.error("\u274C Fatal error starting server:",t),process.exit(1)});
@@ -0,0 +1 @@
1
+ import a from"fs";import l from"path";import{fileURLToPath as x}from"url";const y=l.dirname(x(import.meta.url)),r=l.resolve(y,"../../public/logos/packages"),m="/img/";let c=null;function p(){const e=new Map;if(!a.existsSync(r))return console.warn(`[integration-logos] ${r} not found \u2014 logo fallback disabled`),e;const i=a.readdirSync(r,{withFileTypes:!0});let o=0,n=0;for(const s of i){if(!s.isDirectory())continue;const t=s.name,g=l.join(r,t,"img");if(!a.existsSync(g))continue;let u;try{u=a.readdirSync(g)}catch{continue}for(const d of u){const h=l.join(g,d),f=e.get(d);f?(f.collidingPackages.push(t),n++):(e.set(d,{absolutePath:h,packageName:t,collidingPackages:[]}),o++)}}return console.log(`[integration-logos] Indexed ${o} unique logo filenames from ${r} (${n} collisions ignored \u2014 first match wins)`),e}function I(){return c===null&&(c=p()),c}function E(){c=p()}function R(e,i,o){if(e.method!=="GET"&&e.method!=="HEAD"){o();return}if(!e.path.startsWith(m)){o();return}const n=e.path.slice(m.length);if(!n||n.includes("/")||n.includes("..")){o();return}const s=I().get(n);if(!s){o();return}i.setHeader("Cache-Control","public, max-age=31536000, immutable"),i.sendFile(s.absolutePath,t=>{t&&(console.error(`[integration-logos] sendFile failed for ${n}:`,t.message),i.headersSent||o())})}export{E as rebuildLogoIndex,R as serveIntegrationLogoFallback};
@@ -0,0 +1 @@
1
+ import h from"jsonwebtoken";import{Client as x}from"@elastic/elasticsearch";import{config as P}from"../core/config";import{getCapabilities as l,isTrialExpired as g}from"../core/services/plan-service";const C=new x(P.elasticsearch);function p(t){const r=t.cookies?.token;if(r)return r;const e=t.headers.authorization??"";return e.startsWith("Bearer ")?e.slice(7):e||null}function m(t){try{return h.decode(t)}catch{return null}}function d(t){const r=p(t);if(!r)return!1;const e=m(r);return Array.isArray(e?.roles)&&e.roles.includes("superuser")}function f(t){const r=t.auth?.username;if(r)return r;const e=p(t);return e?m(e)?.username??null:null}async function y(t){try{const e=(await C.security.getUser({username:t}))[t]?.metadata??{};return{plan:e.plan??"trial",metadata:e}}catch{return{plan:"trial",metadata:{}}}}function R(t,r){const e=r.planStatus;return g(r)||e==="expired"?(t.status(403).json({error:"Trial expired. Please upgrade your plan.",code:"TRIAL_EXPIRED"}),!0):e==="cancelled"||e==="past_due"?(t.status(403).json({error:"Subscription inactive. Please update your billing.",code:"SUBSCRIPTION_INACTIVE"}),!0):!1}function F(t,r){return async(e,n,a)=>{if(d(e))return a();const s=f(e);if(!s)return n.status(401).json({error:"Unauthorized"});const{plan:o,metadata:i}=await y(s);if(R(n,i))return;const u=l(o)[t];if(u===null)return a();const c=await r(s);if(c>=u)return n.status(403).json({error:`You have reached the limit of ${u} for your ${o} plan.`,code:"QUOTA_EXCEEDED",quotaField:t,used:c,max:u});a()}}function I(t){return async(r,e,n)=>{if(d(r))return n();const a=f(r);if(!a)return e.status(401).json({error:"Unauthorized"});const{plan:s,metadata:o}=await y(a);if(R(e,o))return;if(!l(s)[t])return e.status(403).json({error:"This feature requires Enterprise plan or above.",code:"PLAN_INSUFFICIENT",requiredPlans:["enterprise","premium"]});n()}}export{I as capabilityGuard,F as quotaGuard};
@@ -0,0 +1 @@
1
+ import{OpenAPIRegistry as O,OpenApiGeneratorV3 as P,extendZodWithOpenApi as j}from"@asteasolutions/zod-to-openapi";import{z as g,ZodObject as q}from"zod";import{protectedRouteDefinitions as x,unprotectedRouteDefinitions as C}from"../routes";import{BRAND_NAME as y}from"../core/app-config/branding";j(g);const v=process.env.STKXP_APP_PUBLIC_URL||"https://localhost:3003";function $(e){return e.replace(/:([A-Za-z0-9_]+)/g,"{$1}")}function b(e){return e instanceof q?e:void 0}function k(e){const i=[],o=/\{([^}]+)\}/g;let r;for(;(r=o.exec(e))!==null;)i.push(r[1]);return i}function A(e,i,o){if(!e.openapi?.summary)return null;const r=e.openapi.audience??"public";if(r==="hidden"||r==="internal"&&o!=="internal")return null;const p=$(e.path),u=e.openapi.security??(i?"bearer":"none"),s={};if(e.openapi.responses)for(const[a,d]of Object.entries(e.openapi.responses))s[a]={description:`${a} response`,content:{"application/json":{schema:d}}};Object.keys(s).length===0&&(s[200]={description:"OK"}),u==="bearer"&&!s[401]&&(s[401]={description:"Unauthorized \u2014 missing or invalid bearer token"});const t={},n=b(e.validate?.params),f=k(p);if(f.length>0){const a={},d=n?.shape??{};for(const h of f)h in d||(a[h]=g.string());Object.keys(a).length>0?t.params=n?n.extend(a):g.object(a):n&&(t.params=n)}else n&&(t.params=n);const m=b(e.validate?.query);m&&(t.query=m),e.validate?.body&&(t.body={content:{"application/json":{schema:e.validate.body}},required:!0});const c=e.openapi.requiredRoles?.length?e.openapi.requiredRoles:void 0,R=c?`\u{1F512} (${c.join(", ")}) ${e.openapi.summary}`:e.openapi.summary,l={method:e.method,path:p,summary:R,description:e.openapi.description,tags:e.openapi.tags??["uncategorized"],deprecated:e.openapi.deprecated,request:Object.keys(t).length>0?t:void 0,responses:s,security:u==="bearer"?[{bearerAuth:[]}]:[]};return c&&(l["x-stkxp-required-roles"]=c),console.log(JSON.stringify({route:`${e.method} ${e.path}`,audience:o,cfg:l},null,2)),l}function I(e={}){const i=e.audience??"public",o=new O;o.registerComponent("securitySchemes","bearerAuth",{type:"http",scheme:"bearer",bearerFormat:"JWT",description:"JWT issued by /api/auth/login"});let r=0,p=0;for(const t of x){const n=A(t,!0,i);n?(o.registerPath(n),p++):r++}for(const t of C){const n=A(t,!1,i);n?(o.registerPath(n),p++):r++}return{doc:new P(o.definitions).generateDocument({openapi:"3.0.0",info:{title:`${y} App API${i==="internal"?" (internal)":""}`,version:"1.0.0",description:`REST API for the ${y} App. Only routes annotated with \`openapi.summary\` appear here \u2014 annotation coverage is opt-in. `+(i==="internal"?"Includes internal-only operations not exposed in the public spec.":"Append `?audience=internal` to see internal-only operations.")},servers:[{url:v,description:"Configured public URL"}]}),stats:{registered:p,skipped:r,audience:i}}}export{I as buildOpenApiDocument};
@@ -0,0 +1 @@
1
+ const e={openapi:"3.0.3",info:{title:"Stack Expert \u2014 Chat HTML Export",version:"1.0.0",description:"Converts a chat message into email-safe HTML (images hosted, CSS inlined, no scripts) for use with an email-sending tool such as resend_send_email."},servers:[{url:process.env.STKXP_APP_PUBLIC_URL||"https://app.erretegia.com"}],paths:{"/api/html/export-chat":{post:{operationId:"convert_chat_to_html",summary:"Convert a chat message to email-safe HTML",description:"Renders the given chat (by chatId, optionally a specific messageId) into a complete, self-contained HTML document suitable for sending as an email body: all images are hosted at public URLs (not inlined as base64) and all CSS is inlined per-element. Pass the returned html directly as the html argument of an email-sending tool.",security:[{ApiKeyAuth:[]}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["chatId"],properties:{chatId:{type:"string",description:'The chat ID to export (see "Current chat ID" in your system prompt).'},messageId:{type:"string",description:"Optional \u2014 a specific message ID. Defaults to the last assistant message."}}}}}},responses:{200:{description:"The rendered email-safe HTML",content:{"application/json":{schema:{type:"object",properties:{html:{type:"string"}}}}}},400:{description:"Validation error or the target message is a system message"},401:{description:"Missing or invalid credentials"},404:{description:"Chat not found, not owned by the caller, or no matching message"}}}}},components:{securitySchemes:{ApiKeyAuth:{type:"apiKey",in:"header",name:"x-api-key"}}}};export{e as HTML_TOOL_OPENAPI_SPEC};
@@ -0,0 +1 @@
1
+ import{Router as h}from"express";import m from"https";import f from"http";const i=h();i.get("/a2a/agent-card",async(u,r)=>{const{agentUrl:c}=u.query;if(!c)return r.status(400).json({error:"agentUrl query parameter is required"});let t;try{t=new URL("/.well-known/agent.json",c)}catch{return r.status(400).json({error:"agentUrl is not a valid URL"})}const d=t.protocol==="https:"?m:f;try{const o=await new Promise((l,a)=>{const n=d.get({hostname:t.hostname,port:t.port||(t.protocol==="https:"?443:80),path:t.pathname+t.search,headers:{Accept:"application/json"},rejectUnauthorized:!1},e=>{let s="";e.setEncoding("utf8"),e.on("data",p=>{s+=p}),e.on("end",()=>{e.statusCode&&e.statusCode>=400?a(new Error(`Remote agent returned HTTP ${e.statusCode}: ${s.slice(0,200)}`)):l(s)}),e.on("error",a)});n.on("error",a),n.setTimeout(5e3,()=>{n.destroy(),a(new Error("Timeout fetching agent card"))})}),g=JSON.parse(o);return r.json(g)}catch(o){return console.error("[A2ARoutes] Failed to fetch agent card:",o.message),r.status(502).json({error:`Failed to fetch agent card: ${o.message}`})}});var E=i;export{E as default};
@@ -0,0 +1,5 @@
1
+ import{createLangGraphService as v}from"../services/langgraph-service";import{resolveCaller as w,hasScope as f,forbiddenScope as g}from"./langgraph";function I(t){const e=t?.params?.id,r=t?.params?.message?.parts,o=(Array.isArray(r)?r.find(d=>d?.type==="text"):void 0)?.text,i=t?.params?.message?.metadata?.teamId;return!e||typeof e!="string"?{error:"Invalid params: params.id is required"}:!o||typeof o!="string"?{error:"Invalid params: message must contain a text part"}:!i||typeof i!="string"?{error:"Invalid params: message.metadata.teamId is required"}:{taskId:e,input:o,teamId:i}}function y(t,e,r){switch(t.type){case"token":case"markdown_token":return{frame:{id:e,status:{state:"working",message:{role:"agent",parts:[{type:"text",text:t.text??""}]}}},isTerminal:!1};case"tool_start":{let a=t.data?.toolName;if(!a&&t.text)try{a=JSON.parse(t.text)?.toolName}catch{}return{frame:{id:e,status:{state:"working",message:{role:"agent",parts:[],metadata:{tool:a}}}},isTerminal:!1}}case"done":return{frame:{id:e,status:{state:"completed"},artifacts:[{parts:[{type:"text",text:r}]}],final:!0},isTerminal:!0,terminalText:r};case"error":case"stream_error":case"api_overloaded":case"rate_limit":case"api_error":return{frame:{id:e,status:{state:"failed",message:{role:"agent",parts:[{type:"text",text:t.error??"Unknown error"}]}}},isTerminal:!0};default:return{frame:null,isTerminal:!1}}}let p=null;async function S(){return p||(p=await v()),p}const T={name:"Stack Expert Team Gateway",description:"Invoke a Team's coordination graph. Set message.metadata.teamId to the target team's id.",skills:[],capabilities:{streaming:!0}},N=[{path:"/.well-known/agent.json",method:"get",requiresAuth:!1,handler:async(t,e)=>{e.json(T)}},{path:"/api/a2a",method:"post",requiresAuth:!1,handler:async(t,e)=>{const r=t.body?.id??null,a=t.body?.method,o=await w(t);if(!o)return e.status(401).json({error:"Unauthorized: missing, invalid, or revoked credentials (Bearer JWT or X-Api-Key)"});if(a!=="tasks/send"&&a!=="tasks/sendSubscribe")return e.status(400).json({jsonrpc:"2.0",id:r,error:{code:-32601,message:`Method not found: ${a}`}});if(!f(o,"agent:execute"))return g(e,"agent:execute");if(a==="tasks/sendSubscribe"&&!f(o,"agent:stream"))return g(e,"agent:stream");const i=I(t.body);if("error"in i)return e.status(400).json({jsonrpc:"2.0",id:r,error:{code:-32602,message:i.error}});const{taskId:d,input:x,teamId:k}=i,l=await S(),u={input:x,teamId:k,threadId:d,runId:d,userToken:o.token};if(a==="tasks/sendSubscribe"){e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),e.setHeader("X-Accel-Buffering","no");try{let s="";for await(const n of l.invoke(u)){(n.type==="token"||n.type==="markdown_token")&&(s+=n.text??"");const{frame:m,isTerminal:c}=y(n,d,s);if(m&&e.write(`data: ${JSON.stringify({jsonrpc:"2.0",id:r,result:m})}
2
+
3
+ `),c)break}}catch(s){e.write(`data: ${JSON.stringify({jsonrpc:"2.0",id:r,result:{id:d,status:{state:"failed",message:{role:"agent",parts:[{type:"text",text:s?.message||"Internal server error"}]}}}})}
4
+
5
+ `)}return e.end()}try{let s="",n=null;for await(const m of l.invoke(u)){(m.type==="token"||m.type==="markdown_token")&&(s+=m.text??"");const{frame:c,isTerminal:h}=y(m,d,s);if(h){n=c;break}}return n?.status?.state==="failed"?e.json({jsonrpc:"2.0",id:r,error:{code:-32e3,message:n.status.message.parts[0].text}}):e.json({jsonrpc:"2.0",id:r,result:n})}catch(s){return e.status(500).json({jsonrpc:"2.0",id:r,error:{code:-32e3,message:s?.message||"Internal server error"}})}}}];export{I as extractA2aRequest,N as routes,y as toA2aFrame};
@@ -0,0 +1 @@
1
+ import b from"zod";import{Client as F}from"@elastic/elasticsearch";import{config as R}from"../core/config";import{userToken as y,updateUser as $,isUsernameExists as I,issueToken as N,activateUser as P}from"../services/auth";import{KibanaService as z}from"../core/services/kibana-service";import{getPlatforms as A}from"../core/services/platforms-service";import{KibanaClientFactory as D}from"../core/services/kibana-client-factory";import{settingsConfig as x}from"../core/app-config/settings";import{resolveClosure as O,createEsStore as v}from"../services/clone/closure-resolver";import{executeClone as M,createEsCloneWriter as C}from"../services/clone/clone-executor";import{getEntitySpec as H}from"../services/clone/entity-graph";const _=`${x.kibana.hostname}:${x.kibana.port}`,k=".stkxp_platforms",h=new F(R.elasticsearch),E=new z,ee=(o,e,d)=>{const s=o.headers.authorization?.split(" ")[1],r=s?y(s):null;if(!r||!r.roles||!r.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});o.user=r,d()},U=[".stkxp_assistants",".stkxp_teams",".stkxp_graphs",".stkxp_prompts",".stkxp_connectors",".stkxp_tools",".stkxp_api",".stkxp_resources",".stkxp_llm_providers",".stkxp_llm_models",".stkxp_llm_routing_rules",".stkxp_mcp_servers",".stkxp_execution_profiles",".stkxp_share_links",".stkxp_triggers",".stkxp_routing_rules",".stkxp_guests",".stkxp_live_resources"],T=[".stkxp_chats",".stkxp_chat_runs",".stkxp_chat_tools",".stkxp_chat_traces",".stkxp_chat_llms"];async function q(o){const e={},d={},n={bool:{should:[{term:{owner:o}},{term:{"metadata.owner":o}}],minimum_should_match:1}};for(const s of U)try{const r=await h.deleteByQuery({index:s,body:{query:n},conflicts:"proceed",refresh:!0});e[s]=r.deleted??0}catch(r){r?.meta?.statusCode!==404&&(d[s]=r.message??"Unknown error")}for(const s of T)try{const r=await h.deleteByQuery({index:s,body:{query:{term:{username:o}}},conflicts:"proceed",refresh:!0});e[s]=r.deleted??0}catch(r){r?.meta?.statusCode!==404&&(d[s]=r.message??"Unknown error")}try{const s=await h.deleteByQuery({index:".stkxp_platforms",body:{query:{bool:{should:[{term:{owner:o}},{term:{"metadata.owner":o}}],minimum_should_match:1,must_not:[{term:{managedType:"managed"}}]}}},conflicts:"proceed",refresh:!0});e[".stkxp_platforms"]=s.deleted??0}catch(s){s?.meta?.statusCode!==404&&(d[".stkxp_platforms"]=s.message??"Unknown error")}return{deleted:e,errors:d}}const re=[{method:"get",path:"/api/stack_expert/admin/users/:username/role",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{username:r}=o.params;try{const a=(await h.security.getRole({name:r}))[r];return a?(console.log("[GET_USER_ROLE] Fetched role data:",JSON.stringify(a,null,2)),e.json({body:{time:new Date().toISOString(),result:{name:r,...a}}})):e.status(404).json({body:{time:new Date().toISOString(),result:{error:"Role not found"}}})}catch(t){return t?.meta?.statusCode===404?e.status(404).json({body:{time:new Date().toISOString(),result:{error:"Role not found"}}}):(console.error("Error fetching user role:",t),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}}))}}},{method:"delete",path:"/api/stack_expert/admin/users/:username/role",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{username:r}=o.params;try{return await h.security.deleteRole({name:r}),e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0,message:"Role deleted successfully"}}})}catch(t){return t.statusCode===404?e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0,message:"Role does not exist"}}}):(console.error("Error deleting user role:",t),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}}))}}},{method:"put",path:"/api/stack_expert/admin/users/:username/role",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{username:r}=o.params,{cluster:t,indices:a,applications:i,run_as:m,metadata:l}=o.body;try{const u=(a||[]).filter(f=>f.names&&Array.isArray(f.names)&&f.names.length>0&&f.privileges&&Array.isArray(f.privileges)&&f.privileges.length>0),c={cluster:t||[],indices:u,applications:i||[],run_as:m||[],metadata:l||{}};console.log("[UPDATE_ROLE] Role body to send:",JSON.stringify(c,null,2));const g=await h.security.putRole({name:r,body:c});return e.status(200).json({body:{time:new Date().toISOString(),result:g}})}catch(u){return console.error("Error updating user role:",u),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"get",path:"/api/stack_expert/admin/users",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});try{const r=await h.security.getUser(),t=Object.entries(r).map(([a,i])=>({username:a,...i}));return e.json({body:{time:new Date().toISOString(),result:{users:t,total:t.length}}})}catch(r){return console.error("Error fetching users:",r),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"get",path:"/api/stack_expert/admin/users/:username",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{username:r}=o.params;try{const t=await I(r),a=t.body?.[r]||t[r];return a?e.json({body:{time:new Date().toISOString(),result:{username:r,...a}}}):e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}})}catch(t){return console.error("Error fetching user:",t),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"put",path:"/api/stack_expert/admin/users/:username",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{username:r}=o.params,{email:t,password:a,roles:i,enabled:m,metadata:l}=o.body;try{const u=await I(r);if(!u.body?.[r]&&!u[r])return e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}});const c=await $(r,t,a,i,m,l);return e.status(200).json({body:{time:new Date().toISOString(),result:c}})}catch(u){return console.error("Error updating user:",u),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"delete",path:"/api/stack_expert/admin/users/:username",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{username:r}=o.params;if(s.username===r)return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"Cannot delete your own account"}}});try{await h.security.deleteUser({username:r})}catch(m){return console.error("Error deleting user:",m),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}const{deleted:t,errors:a}=await q(r),i=Object.values(t).reduce((m,l)=>m+l,0);return console.log(`[ADMIN] Deleted user ${r}: ${i} documents across ${Object.keys(t).length} indices`),Object.keys(a).length>0&&console.warn(`[ADMIN] Cleanup errors for ${r}:`,a),e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0,message:"User deleted successfully",cleanup:{deleted:t,...Object.keys(a).length>0&&{errors:a}}}}})}},{method:"get",path:"/api/stack_expert/admin/policies",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});try{const r=[],t=[];try{const l=D.createFromSettings();console.log("[ADMIN] Fetching policies from default Kibana (settings.ts)...");const u=await l.getPackagePolicies();if(u?.error){const c=u.error?.message||u.error?.code||JSON.stringify(u.error);console.warn(`[ADMIN] Default Kibana Fleet error (HTTP ${u.statusCode??"timeout"}): ${c}`),t.push({source:_,error:`HTTP ${u.statusCode??"timeout"}: ${c}`})}else{const c=u?.data?.items||[];console.log(`[ADMIN] Default Kibana: ${c.length} policies`);for(const g of c)r.push({...g,platformId:"settings",platformName:_})}}catch(l){const u=l?.message||String(l);console.warn("[ADMIN] Default Kibana policies fetch threw:",u),t.push({source:_,error:u})}try{const u=(await h.search({index:k,body:{query:{bool:{must:[{term:{type:"ElasticStack"}},{term:{enabled:!0}}]}},size:500}})).hits?.hits??[];console.log(`[ADMIN] Found ${u.length} enabled ElasticStack platforms`),await Promise.allSettled(u.map(async c=>{const g={_id:c._id,...c._source};try{console.log(`[ADMIN] Fetching policies from platform: ${g.name}...`);const p=await D.createFromPlatform(g).getPackagePolicies();if(p?.error){const S=p.error?.message||p.error?.code||JSON.stringify(p.error);console.warn(`[ADMIN] Platform ${g.name} Fleet error (HTTP ${p.statusCode??"timeout"}): ${S}`),t.push({source:g.name,error:`HTTP ${p.statusCode??"timeout"}: ${S}`})}else{const S=p?.data?.items||[];console.log(`[ADMIN] Platform ${g.name}: ${S.length} policies`);for(const w of S)r.push({...w,platformId:g.id||c._id,platformName:g.name})}}catch(f){const p=f?.message||String(f);console.warn(`[ADMIN] Platform ${g.name} policies fetch threw:`,p),t.push({source:g.name,error:p})}}))}catch(l){const u=l?.message||String(l);console.warn("[ADMIN] Failed to fetch platform list:",u),t.push({source:"ES platform list",error:u})}const a=new Set,i=r.filter(l=>{const u=`${l.platformId}::${l.id}`;return a.has(u)?!1:(a.add(u),!0)}),m=i.reduce((l,u)=>{const c=u.package?.name||"unknown";return l[c]||(l[c]=[]),l[c].push(u),l},{});return console.log(`[ADMIN] Total policies: ${i.length}, errors: ${t.length}`),e.json({body:{time:new Date().toISOString(),result:{policies:i,total:i.length,groupedByPackage:m,...t.length>0?{errors:t}:{}}}})}catch(r){return console.error("Error fetching policies:",r),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"get",path:"/api/stack_expert/admin/platforms",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});const{managedType:r,type:t}=o.query;try{const a=[];r&&a.push({term:{managedType:r}}),t&&a.push({term:{type:t}});const m=((await h.search({index:k,body:{query:a.length?{bool:{must:a}}:{match_all:{}},sort:[{created:{order:"desc"}}],size:500}})).hits?.hits??[]).map(l=>({_id:l._id,...l._source}));return e.json({body:{result:{platforms:m}}})}catch(a){return console.error("Error listing platforms:",a),e.status(500).json({body:{result:{error:"Internal server error"}}})}}},{method:"post",path:"/api/stack_expert/admin/platforms",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});try{const{createPlatform:r}=await import("../core/services/platforms-service"),{name:t,type:a,managedType:i,enabled:m,config:l,owner:u}=o.body,c=await r({name:t,type:a,managedType:i,enabled:m??!0,config:l,owner:u??null});return e.json({body:{result:{platform:c}}})}catch(r){return console.error("Error creating platform:",r),e.status(500).json({body:{result:{error:"Internal server error"}}})}}},{method:"put",path:"/api/stack_expert/admin/platforms/:platformId",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});const{platformId:r}=o.params;try{const t=await h.get({index:k,id:r}),{_id:a,...i}=t._source,{_id:m,...l}=o.body,u={...i,...l,updated:new Date().toISOString()};return await h.index({index:k,id:r,body:u,refresh:!0}),e.json({body:{result:{platform:u}}})}catch(t){return console.error("Error updating platform:",t),e.status(500).json({body:{result:{error:"Internal server error"}}})}}},{method:"delete",path:"/api/stack_expert/admin/platforms/:platformId",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});const{platformId:r}=o.params;try{return await h.delete({index:k,id:r,refresh:!0}),e.json({body:{result:{success:!0}}})}catch(t){return console.error("Error deleting platform:",t),e.status(500).json({body:{result:{error:"Internal server error"}}})}}},{method:"get",path:"/api/stack_expert/admin/users/:username/platforms",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});const{username:r}=o.params;try{const{platforms:t}=await A(r,void 0,void 0,1,1e3);return e.json({body:{result:{platforms:t}}})}catch(t){return console.error("Error fetching platforms for user:",t),e.status(500).json({body:{result:{error:"Internal server error"}}})}}},{method:"delete",path:"/api/stack_expert/admin/users/:username/platforms/:platformId",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});const{platformId:r}=o.params;try{const a=(await h.search({index:k,body:{query:{term:{id:r}},_source:!1,size:1}})).hits.hits[0];if(!a)return e.status(404).json({body:{result:{error:"Platform not found"}}});const i=a._id;return await h.update({index:k,id:i,body:{doc:{owner:null,updated:new Date().toISOString()}},refresh:!0}),e.json({body:{result:{success:!0}}})}catch(t){return t?.meta?.statusCode===404?e.status(404).json({body:{result:{error:"Platform not found"}}}):(console.error("Error unassigning platform:",t),e.status(500).json({body:{result:{error:"Internal server error"}}}))}}},{method:"post",path:"/api/stack_expert/admin/policies/sync-tools",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});const{platformId:r,packageName:t,namespace:a="default"}=o.body;if(!r||!t)return e.status(400).json({body:{result:{error:"platformId and packageName are required"}}});try{const{syncElasticStackPackageTools:i}=await import("../core/services/elastic-stack-sync-service"),u=((await h.search({index:k,body:{query:{bool:{should:[{term:{id:r}},{term:{_id:r}}]}},size:1}})).hits.hits[0]?._source??{}).owner||s.username,c=Buffer.from(`${r}|${t}|${a}`).toString("base64"),g=await i(c,u);return e.json({body:{result:{success:!0,...g}}})}catch(i){return console.error("[ADMIN] Sync tools error:",i.message),e.status(500).json({body:{result:{error:i.message||"Sync failed"}}})}}},{method:"get",path:"/api/stack_expert/admin/policies/tools",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});const{packageName:r,platformId:t}=o.query;if(!r)return e.status(400).json({body:{result:{error:"packageName is required"}}});try{const a=[{term:{system:r}}];t&&a.push({term:{platformId:t}});const m=(await h.search({index:".stkxp_tools",body:{query:{bool:{must:a}},size:200,sort:[{name:{order:"asc",unmapped_type:"keyword"}}]}})).hits.hits.map(l=>({id:l._id,...l._source}));return e.json({body:{result:{tools:m,total:m.length}}})}catch(a){return a?.meta?.statusCode===404?e.json({body:{result:{tools:[],total:0}}}):e.status(500).json({body:{result:{error:a.message}}})}}},{method:"get",path:"/api/stack_expert/admin/policies/api",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden"}}});const{packageName:r,platformId:t,owner:a}=o.query;if(!r)return e.status(400).json({body:{result:{error:"packageName is required"}}});try{const i=[{term:{system:r}}];t&&i.push({term:{platformId:t}}),a&&i.push({term:{owner:a}});const l=(await h.search({index:".stkxp_api",body:{query:{bool:{must:i}},size:200,sort:[{name:{order:"asc",unmapped_type:"keyword"}}]}})).hits.hits.map(u=>({id:u._id,...u._source}));return e.json({body:{result:{apis:l,total:l.length}}})}catch(i){return i?.meta?.statusCode===404?e.json({body:{result:{apis:[],total:0}}}):e.status(500).json({body:{result:{error:i.message}}})}}},{method:"get",path:"/api/stack_expert/admin/policies/:packageName",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{packageName:r}=o.params;try{const t=await E.getPackagePolicies(),m=((t?.data||t)?.items||[]).filter(l=>l.package?.name===r);return e.json({body:{time:new Date().toISOString(),result:{packageName:r,policies:m,total:m.length}}})}catch(t){return console.error("Error fetching policies:",t),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"delete",path:"/api/stack_expert/admin/policies/:policyId",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{policyId:r}=o.params;try{return await E.deletePackagePolicy(r),e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0,message:"Policy deleted successfully"}}})}catch(t){return console.error("Error deleting policy:",t),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"post",path:"/api/stack_expert/admin/users/:username/activate",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{username:r}=o.params;try{const t=await I(r);if(!(t?.body?.[r]??t?.[r]))return e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}});const i=await P(r);return console.log(`[ADMIN] Manual activation of ${r} by ${s.username}`),e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0,username:r,activated:!0,details:i}}})}catch(t){return console.error(`Error activating user ${r}:`,t),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"post",path:"/api/stack_expert/admin/users/:username/impersonate",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s||!s.roles||!s.roles.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden: Superuser role required"}}});const{username:r}=o.params;try{const a=(await h.security.getUser({username:r}))[r];if(!a)return e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}});const i=a.roles??[];if(i.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Cannot impersonate a superuser"}}});const m=N(r,i,null,a.enabled??!0);return e.json({body:{time:new Date().toISOString(),result:{token:m,username:r,roles:i,enabled:a.enabled??!0}}})}catch(t){return console.error("Error impersonating user:",t),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"post",path:"/api/stack_expert/admin/clone/preview",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1];if(!(n?y(n):null)?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden: Superuser role required"}}});const t=b.object({sourceOwner:b.string().min(1),targetUsername:b.string().min(1),roots:b.array(b.object({index:b.string().min(1),esId:b.string().min(1)})).min(1)}).safeParse(o.body);if(!t.success)return e.status(400).json({body:{result:{error:"Invalid request",details:t.error.issues}}});const{sourceOwner:a,targetUsername:i,roots:m}=t.data;try{const l=v(h),u=await O(m,a,l),c={},g=u.docs.map(p=>{const S=H(p.key);return c[p.key]=(c[p.key]??0)+1,{key:p.key,index:p.index,esId:p.esId,name:S.nameField?p.source[S.nameField]:void 0,reachedVia:p.reachedVia}}),f=[];for(const p of u.docs){const S=H(p.key),w=S.nameField?p.source[S.nameField]:void 0;if(!S.nameField||typeof w!="string"||w.length===0)continue;const j=await l.findByName(S.index,S.nameField,w,[i]);j.length&&f.push({key:p.key,esId:p.esId,name:w,existingEsId:j[0]._id})}return e.json({body:{time:new Date().toISOString(),result:{sourceOwner:a,targetUsername:i,summary:{totalDocs:u.docs.length,byEntity:c},docs:g,unresolved:u.unresolved,wouldSkip:f}}})}catch(l){return console.error("Error previewing clone:",l),e.status(500).json({body:{result:{error:l?.message??"Internal server error"}}})}}},{method:"post",path:"/api/stack_expert/admin/clone/execute",validate:{},handler:async function(o,e){const n=o.headers.authorization?.split(" ")[1],s=n?y(n):null;if(!s?.roles?.includes("superuser"))return e.status(403).json({body:{result:{error:"Forbidden: Superuser role required"}}});const t=b.object({sourceOwner:b.string().min(1),targetUsername:b.string().min(1),roots:b.array(b.object({index:b.string().min(1),esId:b.string().min(1)})).min(1),blankSecrets:b.boolean().optional()}).safeParse(o.body);if(!t.success)return e.status(400).json({body:{result:{error:"Invalid request",details:t.error.issues}}});const{sourceOwner:a,targetUsername:i,roots:m,blankSecrets:l}=t.data;try{const u=await I(i);if(!(u?.body?.[i]||u?.[i]))return e.status(404).json({body:{result:{error:`Target user "${i}" not found`}}})}catch{return e.status(404).json({body:{result:{error:`Target user "${i}" not found`}}})}try{const u=v(h),c=C(h),g=await O(m,a,u),f=await M(g,i,u,c,{blankSecrets:l!==!1});return console.log(`[clone] ${s.username??"admin"} cloned ${m.length} root(s) from "${a}" \u2192 "${i}": ${f.created.length} created, ${f.skipped.length} skipped, ${f.droppedRefs.length} refs dropped`),e.json({body:{time:new Date().toISOString(),result:{sourceOwner:a,targetUsername:i,unresolved:g.unresolved,report:f}}})}catch(u){console.error("Error executing clone:",u);const c=/Required dependencies/.test(u?.message??"")?422:500;return e.status(c).json({body:{result:{error:u?.message??"Internal server error"}}})}}}];export{re as routes};
@@ -0,0 +1 @@
1
+ import{randomUUID as L}from"crypto";import{z as b}from"zod";import{getMcpServerCapabilities as N}from"../core/services/mcp-servers-service";import{assertOwner as E,getAuthUsername as j,isSuperuser as B}from"../core/utils/ownership";import{makeOwnerScopedClient as W}from"../core/utils/owner-scope";import{userToken as H}from"../services/auth";import{projectAssistantTokens as C}from"../core/services/token-projection-service";import{snapshotBeforeUpdate as V}from"../core/services/version-snapshot-service";const J=process.env.ELASTICSEARCH_HOST||"https://51.159.174.230:9205",Q=process.env.ELASTICSEARCH_USER||"elastic",X=process.env.ELASTICSEARCH_PASSWORD||"",R=".stkxp_assistants",G=".stkxp_chats",Y=".stkxp_chat_llms",f=W({node:J,auth:{username:Q,password:X},tls:{rejectUnauthorized:!1},requestTimeout:6e4,maxRetries:3}),q=b.object({packageName:b.string().optional(),topic:b.string().optional(),systems:b.string().optional(),enabled:b.string().optional().transform(o=>{if(o!==void 0)return o==="true"}),page:b.string().optional().transform(o=>o?parseInt(o,10):1),pageSize:b.string().optional().transform(o=>o?parseInt(o,10):25),limit:b.string().optional().transform(o=>o?parseInt(o,10):void 0),search:b.string().optional().describe("Hybrid lexical + semantic search across name, role, instructions, tags, topic"),tags:b.string().optional(),owner:b.string().optional(),owners:b.string().optional(),includeSystem:b.string().optional().transform(o=>o==="true"||o==="1"),graphId:b.string().optional()});function Z(o,t){const s=new Set;s.add("*");const a=o.replace(/_/g,"|"),l=a.split("|").filter(e=>e.trim()),c=[];l.forEach(e=>{(c.length===0||e!==c[c.length-1])&&c.push(e)}),c.forEach(e=>s.add(e));for(let e=0;e<c.length;e++)for(let i=e+1;i<=c.length;i++){const p=c.slice(e,i).join("|");s.add(p)}return t&&(s.add(t),[...s].map(i=>i!=="*"&&i!==t?`${t}|${i}`:i).forEach(i=>s.add(i))),s.add(a),o!==a&&s.add(o),Array.from(s)}async function K(o,t){try{const s=q.parse(o.query),a=[];if(s.packageName){const d=s.packageName==="stack_expert"?"clusters":s.packageName;console.log(`[Assistants API] Package filter: ${s.packageName} \u2192 ${d}`);try{const m=(await f.search({index:".stkxp_platforms",body:{query:{bool:{must:[{term:{type:"MCPServer"}},{term:{"config.packageName":d}}]}},size:1e4,_source:["name"]}})).hits.hits.map(g=>g._source?.name).filter(Boolean);if(console.log(`[Assistants API] Found ${m.length} MCP servers with packageName: ${d}`,m),m.length>0)a.push({bool:{should:m.map(g=>({term:{"mcp_servers_policy.servers.name.keyword":g}})),minimum_should_match:1}});else return console.log(`[Assistants API] No MCP servers found with packageName: ${d} - returning empty result`),t.json({success:!0,count:0,total:0,page:s.page||1,pageSize:s.pageSize||25,totalPages:0,assistants:[]})}catch(_){console.error("[Assistants API] Error fetching MCP servers by packageName:",_)}}if(s.topic){const d=Z(s.topic,s.packageName);console.log(`[Assistants API] Topic variations (${d.length}):`,d),a.push({bool:{should:d.map(_=>({term:{topic:_}})),minimum_should_match:1}})}const l={stack_expert:"clusters"};if(s.systems){const d=s.systems.split(",").map(_=>_.trim()).filter(Boolean);if(d.length>0){const _=d.flatMap(g=>{const T=l[g];return T?[g,T]:[g]});console.log("[Assistants API] Systems filter (expanded):",_);let m=[];if(s.owner)try{m=(await f.search({index:".stkxp_platforms",body:{query:{bool:{must:[{term:{type:"MCPServer"}},{term:{"config.serverType":"remote"}},{term:{owner:s.owner}}]}},size:1e3,_source:["name"]}})).hits.hits.map(T=>T._source?.name).filter(Boolean),console.log(`[Assistants API] Remote servers for owner "${s.owner}":`,m)}catch(g){console.error("[Assistants API] Error fetching remote servers:",g.message)}a.push({bool:{should:[..._.flatMap(g=>[{term:{"mcp_servers_policy.servers.name.keyword":g}}]),...m.map(g=>({term:{"mcp_servers_policy.servers.name.keyword":g}}))],minimum_should_match:1}})}}const c=s.enabled!==void 0?s.enabled:!0;if(s.search){const d=s.search.replace(/[+\-&|!(){}[\]^"~:\\\/]/g,"\\$&"),_=/[*?]/.test(d)?d:`*${d}*`;a.push({bool:{should:[{query_string:{query:_,fields:["name^3","context.role^2","behavior.detailed_instructions^1.5","content","tags^2","topic"],default_operator:"AND",analyze_wildcard:!0}},{semantic:{field:"search_semantic",query:s.search}}],minimum_should_match:1}})}if(s.graphId&&a.push({term:{graphId:s.graphId}}),s.tags){const d=s.tags.split(",").map(_=>_.trim()).filter(Boolean);d.length>0&&a.push({terms:{tags:d}})}s.owner&&a.push({term:{owner:s.owner}});const e=s.owners?s.owners.split(",").map(d=>d.trim()).filter(Boolean):[];e.length>0&&a.push({bool:{should:e.map(d=>({term:{owner:d}})),minimum_should_match:1}});const i=s.includeSystem||e.includes("stkxp")||s.owner==="stkxp",p=s.page||1,n=s.limit||s.pageSize||25,u=(p-1)*n,y={name:"name",updated_at:"updated_at"},r=String(o.query.sortField||"name"),h=y[r]||"name",w=o.query.sortOrder==="desc"?"desc":"asc",I={index:R,body:{query:{bool:{must:a.length>0?a:[{match_all:{}}],should:[{constant_score:{filter:{bool:{filter:[{exists:{field:"behavior.detailed_instructions"}}],must_not:[{term:{"behavior.detailed_instructions.keyword":""}}]}},boost:2}},{constant_score:{filter:{bool:{filter:[{exists:{field:"behavior.task_brief"}}],must_not:[{term:{"behavior.task_brief.keyword":""}}]}},boost:1.5}}],...i?{}:{must_not:[{term:{owner:"stkxp"}}]}}},sort:[{_score:{order:"desc"}},{[h]:{order:w}},{"routing.priority":{order:"desc"}}],from:u,size:n}};console.log("[Assistants API] Fetching assistants:",{packageName:s.packageName,topic:s.topic,systems:s.systems,enabled:s.enabled!==void 0?s.enabled:"default (active)",search:s.search,page:p,pageSize:n,from:u,must:JSON.stringify(a,null,2),includeStkxp:i});const x=await f.search(I);console.log("[Assistants API] Elasticsearch response:",x);const k=typeof x.hits.total=="number"?x.hits.total:x.hits.total?.value||0;console.log("[Assistants API] Found:",k,"total assistants, returning",x.hits.hits.length);const A=x.hits.hits.map(d=>({id:d._id,...d._source}));t.json({success:!0,count:A.length,total:k,page:p,pageSize:n,totalPages:Math.ceil(k/n),assistants:A})}catch(s){if(console.error("[Assistants API] Error fetching assistants:",s),s instanceof b.ZodError)return t.status(400).json({success:!1,error:"Invalid query parameters",details:s.errors});t.status(500).json({success:!1,error:"Failed to fetch assistants",message:s.message})}}async function ss(o,t){try{const{id:s}=o.params;if(s.startsWith("team-"))return t.status(404).json({success:!1,error:"Assistant not found"});const a=await f.get({index:R,id:s});if(!a.found)return t.status(404).json({success:!1,error:"Assistant not found"});const l={id:a._id,...a._source};t.json({success:!0,assistant:l})}catch(s){if(s.meta?.statusCode===404)return t.status(404).json({success:!1,error:"Assistant not found"});console.error("[Assistants API] Error fetching assistant:",s),t.status(500).json({success:!1,error:"Failed to fetch assistant",message:s.message})}}async function ts(o,t){try{const s=o.body;if(typeof s.name=="string"&&/[/\\]/.test(s.name))return t.status(400).json({success:!1,error:"Invalid assistant name",message:"Name cannot contain slashes (/ or \\)"});const a=new Date().toISOString();s.created_at=a,s.updated_at=a,s.version||(s.version="1.0.0");const l=o.auth?.username;l?s.owner=l:s.owner||(s.owner="system"),s.tags||(s.tags=[]),s.metadata||(s.metadata={status:"active",cluster_scope:"single_cluster"}),console.log("[Assistants API] Creating assistant:",s.name);let c=s.id;c||(c=L());const{id:e,...i}=s,p=await f.index({index:R,id:c,body:i,refresh:"wait_for"});console.log("[Assistants API] Created assistant:",p._id),t.status(201).json({success:!0,assistant:{id:p._id,...i}})}catch(s){console.error("[Assistants API] Error creating assistant:",s),t.status(500).json({success:!1,error:"Failed to create assistant",message:s.message})}}async function es(o,t){try{const{id:s}=o.params,a=await E(o,t,f,R,s);if(!a)return;await V("assistant",s,a.source,"manual_edit",j(o)||"system");const l=o.body;if(typeof l.name=="string"&&/[/\\]/.test(l.name))return t.status(400).json({success:!1,error:"Invalid assistant name",message:"Name cannot contain slashes (/ or \\)"});l.updated_at=new Date().toISOString(),console.log("[Assistants API] Updating assistant:",s);const{id:c,...e}=l,i=await f.update({index:R,id:s,body:{doc:e},refresh:"wait_for"});console.log("[Assistants API] Updated assistant:",i._id),t.json({success:!0,assistant:{id:i._id,...e}})}catch(s){if(console.error("[Assistants API] Error updating assistant:",s),s.meta?.statusCode===404)return t.status(404).json({success:!1,error:"Assistant not found"});t.status(500).json({success:!1,error:"Failed to update assistant",message:s.message})}}async function as(o,t){try{const{id:s}=o.params;if(!await E(o,t,f,R,s))return;console.log("[Assistants API] Deleting assistant:",s);const l=await f.delete({index:R,id:s,refresh:"wait_for"});console.log("[Assistants API] Deleted assistant:",l._id),t.json({success:!0,message:"Assistant deleted successfully"})}catch(s){if(console.error("[Assistants API] Error deleting assistant:",s),s.meta?.statusCode===404)return t.status(404).json({success:!1,error:"Assistant not found"});t.status(500).json({success:!1,error:"Failed to delete assistant",message:s.message})}}async function ns(o,t){try{const l=((await f.search({index:R,body:{query:{match_all:{}},size:0,aggs:{all_tags:{terms:{field:"tags",size:1e3,order:{_key:"asc"}}}}}})).aggregations?.all_tags?.buckets||[]).map(c=>c.key).filter(Boolean);t.json({success:!0,tags:l})}catch(s){console.error("[Assistants API] Error fetching tags:",s),t.status(500).json({success:!1,error:"Failed to fetch tags",message:s.message})}}async function os(o,t){try{const{servers:s}=o.body;if(!Array.isArray(s)||s.length===0)return t.json({options:[]});const a=new Map;for(const n of s)!n.id||n.id.startsWith("__personal_tools__:")||a.has(n.id)||a.set(n.id,n.name||n.id);if(a.size===0)return t.json({options:[]});const l=await Promise.all(Array.from(a.entries()).map(async([n,u])=>{try{const y=await f.get({index:".stkxp_platforms",id:n});return{id:n,doc:y._source}}catch(y){if(y.meta?.statusCode===404&&u)try{const r=await f.search({index:".stkxp_platforms",body:{query:{term:{name:u}},size:1}});if(r.hits.hits.length>0){const h=r.hits.hits[0];return{id:h._id,doc:h._source}}}catch{}return{id:n,doc:null}}})),c=l.map(n=>n.id),e=new Map;try{const n=await f.search({index:".stkxp_tools",body:{query:{terms:{platformId:c}},_source:["platformId","system"],size:c.length*3}});for(const u of n.hits.hits){const y=u._source;y?.platformId&&y?.system&&!e.has(y.platformId)&&e.set(y.platformId,y.system)}}catch{}const i=new Set,p=[];for(const{id:n,doc:u}of l){const y=u?.name||a.get(n)||n,r=u?.config?.namespace||u?.namespace||y;if(i.has(n))continue;i.add(n);const h=u?.config?.url||null;let w=e.get(n)||u?.system||"";if(!w&&h)try{const I=new URL(h).pathname.split("/").filter(Boolean);w=I[I.length-1]||""}catch{}w||(w=y),p.push({serverId:n,serverName:y,namespace:r,system:w,mcpUrl:h})}t.json({options:p})}catch(s){t.status(500).json({error:s.message})}}function rs(o){try{let t=o.cookies?.token;if(!t){const s=o.headers.authorization;s?.startsWith("Bearer ")&&(t=s.substring(7))}return t&&H(t)?.username||null}catch{return null}}async function is(o,t){try{const{id:s}=o.params,a=o.body,l=rs(o),c=a?.mcp_servers_policy;if(!c?.servers||c.servers.length===0)return t.json({servers:[],totalTools:0,totalExcluded:0,effectiveTools:0});const e=await Promise.all(c.servers.map(async n=>{try{if(n.id?.startsWith("__personal_tools__:")){const k=n.id.replace("__personal_tools__:","");console.log(`[getMcpTools] Personal tools server for user: ${k}`);const d=(await f.search({index:".stkxp_tools",body:{query:{bool:{must:[{term:{owner:k}}],should:[{bool:{must:[{term:{type:"mcp"}}],must_not:[{exists:{field:"system"}}]}},{term:{type:"assistant_mapping"}}],minimum_should_match:1}},size:1e4,_source:["name","label","description"]}})).hits.hits.map(_=>({name:_._source.name,label:_._source.label,description:_._source.description,excluded:n.excluded_tools?.includes(_._source.name)||!1}));return{id:n.id,name:n.name,type:"personal",enabled:n.enabled,packageName:null,namespace:null,owner:k,tools:d,toolsCount:d.length,excludedCount:d.filter(_=>_.excluded).length}}let u=null;try{u=(await f.get({index:".stkxp_platforms",id:n.id}))._source}catch(k){if(k.meta?.statusCode===404&&n.name){console.warn(`[getMcpTools] Server ID ${n.id} not found, falling back to name lookup: ${n.name}`);const A=await f.search({index:".stkxp_platforms",body:{query:{term:{name:n.name}},size:1}});A.hits.hits.length>0&&(u=A.hits.hits[0]._source)}else throw k}const y=u?.type||"MCPServer",r=u?.config?.serverType||"local",h=y==="MCPServer"&&(r==="remote"||r==="gateway"),w=y==="OpenAPI"||y==="AsyncAPI"||y==="Toolbox",I=w?"connector":h?"remote":r;let x;if(w){const k=u?.name||n.name;console.log(`[getMcpTools] ${y} connector ${k} \u2014 querying .stkxp_tools by platformId: ${n.id}`),x=(await f.search({index:".stkxp_tools",body:{query:{bool:{should:[{term:{platformId:n.id}},{term:{system:k}}],minimum_should_match:1}},size:1e4,_source:["name","label","description"]}})).hits.hits.map(d=>({name:d._source.name,label:d._source.label,description:d._source.description,excluded:n.excluded_tools?.includes(d._source.name)||!1}))}else if(h){console.log(`[getMcpTools] Remote server ${n.name} \u2014 querying .stkxp_tools by mcpServerId: ${n.id}`);const k=await f.search({index:".stkxp_tools",body:{query:{bool:{must:[{term:{type:"mcp_remote"}},{term:{mcpServerId:n.id}}]}},size:1e4,_source:["name","label","description"]}});k.hits.hits.length>0?x=k.hits.hits.map(A=>({name:A._source.name,label:A._source.label,description:A._source.description,excluded:n.excluded_tools?.includes(A._source.name)||!1})):(console.log(`[getMcpTools] No synced tools for remote server ${n.name} \u2014 live capabilities call`),x=(await N(n.id)).tools.map(d=>({name:d.name,label:d.name,description:d.description,excluded:n.excluded_tools?.includes(d.name)||!1})))}else{let k=n.packageName||u?.config?.packageName||u?.packageName;if(!k)return console.warn(`[getMcpTools] Managed server ${n.id} has no packageName - skipping`),{id:n.id,name:n.name,type:I,enabled:n.enabled,packageName:null,owner:u?.owner||null,tools:[],toolsCount:0,excludedCount:0};console.log(`[getMcpTools] Managed server ${n.name} \u2014 querying .stkxp_tools by system: ${k}, owner: ${l||"any"}`);const A=l?{bool:{must:[{term:{system:k}},{term:{owner:l}}]}}:{term:{system:k}},d=await f.search({index:".stkxp_tools",body:{query:A,size:1e4,_source:["name","label","description","topic"]}});if(d.hits.hits.length>0)x=d.hits.hits.map(_=>({name:_._source.name,label:_._source.label,description:_._source.description,topic:_._source.topic,excluded:n.excluded_tools?.includes(_._source.name)||!1}));else{console.log(`[getMcpTools] Falling back to live MCP server query for ${n.id}`);try{x=(await N(n.id)).tools.map(m=>({name:m.name,label:m.name,description:m.description,excluded:n.excluded_tools?.includes(m.name)||!1}))}catch(_){console.warn(`[getMcpTools] Live MCP query failed for ${n.id}: ${_.message}`),x=[]}}}return{id:n.id,name:n.name,type:I,enabled:n.enabled,packageName:u?.config?.packageName||u?.packageName||null,namespace:u?.config?.namespace||u?.namespace||null,owner:u?.owner||null,tools:x,toolsCount:x.length,excludedCount:x.filter(k=>k.excluded).length}}catch(u){return console.error(`[getMcpTools] Error loading tools for server ${n.id}:`,u),{id:n.id,name:n.name,type:"unknown",enabled:n.enabled,packageName:null,namespace:null,tools:[],toolsCount:0,excludedCount:0}}})),i=e.reduce((n,u)=>n+u.toolsCount,0),p=e.reduce((n,u)=>n+u.excludedCount,0);t.json({servers:e,totalTools:i,totalExcluded:p,effectiveTools:i-p})}catch(s){console.error("[getMcpTools] Error loading MCP tools:",s),t.status(500).json({error:"Failed to load MCP tools",details:s.message})}}async function z(o,t=5,s=new Set){if(s.has(o)||t<=0)return{};s.add(o);let a;try{const e=await f.get({index:".stkxp_graphs",id:o});if(!e.found)return{};a={id:e._id,...e._source}}catch{return{}}const l={[o]:a},c=(a.nodes||[]).filter(e=>e.type==="subgraph"&&e.graphId).map(e=>e.graphId);return await Promise.all(c.map(async e=>{const i=await z(e,t-1,s);Object.assign(l,i)})),l}async function cs(o){const t=o?.mcp_servers_policy?.servers||[];if(t.length===0)return{};const s={};return await Promise.all(t.map(async a=>{const l=new Set(a.excluded_tools||[]);let c=[];try{if(a.id?.startsWith("__personal_tools__:")){const e=a.id.replace("__personal_tools__:","");c=(await f.search({index:".stkxp_tools",body:{query:{bool:{must:[{term:{owner:e}}],should:[{bool:{must:[{term:{type:"mcp"}}],must_not:[{exists:{field:"system"}}]}},{term:{type:"assistant_mapping"}}],minimum_should_match:1}},size:500,_source:!0}})).hits.hits.map(p=>$({id:p._id,...p._source}))}else{let e=null;try{e=(await f.get({index:".stkxp_platforms",id:a.id}))._source}catch{if(a.name){const r=await f.search({index:".stkxp_platforms",body:{query:{term:{name:a.name}},size:1}});r.hits.hits.length>0&&(e=r.hits.hits[0]._source)}}const i=e?.type||"MCPServer",p=i==="OpenAPI"||i==="AsyncAPI"||i==="Toolbox",n=i==="MCPServer"&&(e?.config?.serverType==="remote"||e?.config?.serverType==="gateway");let u;if(p){const r=e?.name||a.name;u={bool:{should:[{term:{platformId:a.id}},{term:{system:r}}],minimum_should_match:1}}}else if(n)u={bool:{must:[{term:{type:"mcp_remote"}},{term:{mcpServerId:a.id}}]}};else{const r=a.packageName||e?.config?.packageName||e?.packageName;if(!r)return;u={term:{system:r}}}c=(await f.search({index:".stkxp_tools",body:{query:u,size:500,_source:!0}})).hits.hits.map(r=>$({id:r._id,...r._source}))}s[a.name]={serverId:a.id,serverName:a.name,included:c.filter(e=>!l.has(e.name)),excluded:c.filter(e=>l.has(e.name))}}catch(e){console.warn(`[getAssistantMapping] Failed to resolve tools for server ${a.id}:`,e.message)}})),s}function $(o){const t={...o};if(typeof t.inputSchema=="string")try{t.inputSchema=JSON.parse(t.inputSchema)}catch{}if(typeof t.outputSchema=="string")try{t.outputSchema=JSON.parse(t.outputSchema)}catch{}return t}function O(o,t,s=0,a=""){const l=t[o];if(!l)return[];const c=" ".repeat(s),e=[],i={},p={};for(const r of l.edges||[])i[r.from]||(i[r.from]=[]),i[r.from].push(r.to),r.condition&&(p[`${r.from}\u2192${r.to}`]=r.condition);const n={};for(const r of l.nodes||[])n[r.id]=r;const u=new Set,y=["__start__"];for(;y.length>0;){const r=y.shift();if(!u.has(r)){if(u.add(r),r!=="__start__"){const h=n[r],w={depth:s,prefix:a||o,graphId:o,graphName:l.name,nodeId:r,nodeType:r==="__end__"?"__end__":h?.type||"unknown",label:h?.name||h?.id||r};if(h?.interrupt_type&&(w.interrupt={type:h.interrupt_type,message:h.interrupt_message}),e.push(w),h?.type==="subgraph"&&h.graphId){const I=O(h.graphId,t,s+1,h.id);e.push(...I)}}for(const h of i[r]||[])u.has(h)||y.push(h)}}return e}async function ls(o){const t=new Set;for(const c of Object.values(o))for(const e of c.nodes||[])e.llm_routing_rule_id&&t.add(e.llm_routing_rule_id);if(t.size===0)return{};const s=await f.mget({index:".stkxp_llm_routing_rules",body:{ids:[...t]}}),a={},l=new Set;for(const c of s.docs||[]){if(!c.found)continue;const e=c._source,i={id:c._id,name:e.name,modelId:e.modelId||e.llmModelId,temperature:e.temperature,maxTokens:e.maxTokens,strategy:e.strategy,model:null};a[c._id]=i,i.modelId&&l.add(i.modelId)}if(l.size>0)try{const c=await f.mget({index:".stkxp_llm_models",body:{ids:[...l]}}),e={};for(const i of c.docs||[]){if(!i.found)continue;const p=i._source;e[i._id]={id:i._id,name:p.name||p.modelId||p.id,provider:p.provider,contextWindow:p.contextWindow||p.context_window,costInputPer1M:p.costInputPer1M??p.input_cost_per_token,costOutputPer1M:p.costOutputPer1M??p.output_cost_per_token}}for(const i of Object.values(a))i.modelId&&e[i.modelId]&&(i.model=e[i.modelId])}catch{}return a}async function F(o){try{const t=await f.search({index:".stkxp_teams",body:{query:{term:{assistantIds:o}},size:200,_source:["name","enabled","assistants"]}}),s=[];for(const a of t.hits?.hits||[]){const l=a._source;if(!l.enabled)continue;const c=(l.assistants||[]).find(e=>e.id===o);!c||c.enabled===!1||s.push({id:a._id,name:l.name,condition:c.condition||null,runAlways:c.runAlways||!1})}return s}catch{return[]}}async function ds(o,t){try{const{id:s}=o.params;let a;try{const r=await f.get({index:".stkxp_assistants",id:s});if(!r.found)return t.status(404).json({success:!1,error:"Assistant not found"});a={id:r._id,...r._source}}catch(r){if(r.meta?.statusCode===404)return t.status(404).json({success:!1,error:"Assistant not found"});throw r}const l=a.graphId;if(!l){const r=await F(a.id);return t.json({success:!0,mapping:{assistant:a,graphTree:{},routingRules:{},tools:{},flow:[],teams:r}})}const[c,e,i]=await Promise.all([z(l),cs(a),F(a.id)]),p=await ls(c),n=O(l,c),u=o.query.slim==="true";let y=e;if(u){y={};for(const[r,h]of Object.entries(e)){const w=({inputSchema:I,outputSchema:x,openApiMeta:k,authConfig:A,...d})=>d;y[r]={...h,included:h.included.map(w),excluded:h.excluded.map(w)}}}t.json({success:!0,mapping:{assistant:{id:a.id,name:a.name,topic:a.topic,graphId:l,tags:a.tags,updatedAt:a.updatedAt||a.updated_at,mcpServers:a.mcp_servers_policy?.servers?.map(r=>({id:r.id,name:r.name,enabled:r.enabled,excludedTools:r.excluded_tools||[]}))||[]},graphTree:c,routingRules:p,tools:y,flow:n,teams:i}})}catch(s){console.error("[getAssistantMapping] Error:",s),t.status(500).json({success:!1,error:"Failed to build assistant mapping",message:s.message})}}async function us(o,t){try{const{id:s}=o.params;if(!j(o))return t.status(401).json({success:!1,error:"Unauthorized"});if(s.startsWith("team-"))return t.status(404).json({success:!1,error:"Assistant not found"});let l;try{l=(await f.get({index:R,id:s}))._source}catch(e){if(e?.meta?.statusCode===404)return t.status(404).json({success:!1,error:"Assistant not found"});throw e}const c=await C(f,s,l);t.json({success:!0,...c,note:"Single-pass upper bound. Tool loops can exceed it \u2014 multiply by an empirical factor (2-3\xD7) when sizing a budget."})}catch(s){console.error("[Assistants API] Error computing token projection:",s),t.status(500).json({success:!1,error:"Failed to compute token projection",message:s.message})}}async function ms(o,t){try{const{id:s}=o.params,a=j(o);if(!a)return t.status(401).json({success:!1,error:"Unauthorized"});if(s.startsWith("team-"))return t.status(404).json({success:!1,error:"Assistant not found"});const l=Math.min(parseInt(o.query.limit||"20",10)||20,100),c=[{term:{assistantId:s}}];B(o)||c.push({term:{username:a}});const e=await f.search({index:Y,body:{size:l,sort:[{createdAt:{order:"desc"}}],_source:["chatId","runId","teamId","createdAt","llms"],query:{bool:{must:c}}}}),i=(m,g)=>m.reduce((T,M)=>T+Number(M?.[g]||0),0),p=new Map,u=(e.hits.hits||[]).map(m=>{const g=m._source||{},T=Array.isArray(g.llms)?g.llms:[],M=i(T,"inputTokens"),D=i(T,"outputTokens"),U=T.reduce((S,P)=>S+Number(P?.totalTokens||Number(P?.inputTokens||0)+Number(P?.outputTokens||0)),0);for(const S of T){const P=S?.nodeId||"(unattributed)",v=p.get(P)||{nodeId:P,modelId:S?.modelId,provider:S?.provider,totalTokens:0,inputTokens:0,outputTokens:0,calls:0};v.totalTokens+=Number(S?.totalTokens||Number(S?.inputTokens||0)+Number(S?.outputTokens||0)),v.inputTokens+=Number(S?.inputTokens||0),v.outputTokens+=Number(S?.outputTokens||0),v.calls+=1,!v.modelId&&S?.modelId&&(v.modelId=S.modelId),p.set(P,v)}return{chatId:g.chatId,runId:g.runId,teamId:g.teamId,createdAt:g.createdAt,totalTokens:U,inputTokens:M,outputTokens:D,llmCallsCount:T.length}}),y=[...new Set(u.map(m=>m.chatId).filter(Boolean))],r=new Map;if(y.length>0)try{const m=await f.mget({index:G,body:{ids:y,_source:["title","teamName"]}});for(const g of m.docs)g?.found&&r.set(g._id,{title:g._source?.title,teamName:g._source?.teamName})}catch{}const h=u.map(m=>({...m,title:r.get(m.chatId)?.title,teamName:r.get(m.chatId)?.teamName})),w=h.map(m=>m.totalTokens).filter(m=>m>0),I=w.reduce((m,g)=>m+g,0),x=[...w].sort((m,g)=>m-g),k=x.length?x[Math.min(x.length-1,Math.floor(x.length*.95))]:0,A=h.map(m=>m.inputTokens),d=h.map(m=>m.outputTokens),_=[...p.values()].sort((m,g)=>g.totalTokens-m.totalTokens);t.json({success:!0,runCount:w.length,avgTotalTokens:w.length?Math.round(I/w.length):0,maxTotalTokens:w.length?Math.max(...w):0,p95TotalTokens:k,avgInputTokens:A.length?Math.round(A.reduce((m,g)=>m+g,0)/A.length):0,avgOutputTokens:d.length?Math.round(d.reduce((m,g)=>m+g,0)/d.length):0,recentRuns:h,byNode:_})}catch(s){console.error("[Assistants API] Error fetching token stats:",s),t.status(500).json({success:!1,error:"Failed to fetch token stats",message:s.message})}}const ps=b.object({name:b.string().describe("Assistant name (no slashes \u2014 the doc id is derived from it)"),graphId:b.string().optional().describe("Id of the .stkxp_graphs skill/graph this assistant runs"),topic:b.string().optional().describe("Topic used for routing"),description:b.string().optional().describe("Human description"),tags:b.array(b.string()).optional().describe("Free-form tags"),tools:b.array(b.any()).optional().describe("Tool bindings"),llmRoutingRuleId:b.string().optional().describe("LLM routing rule id")}).passthrough(),gs=b.object({servers:b.array(b.object({id:b.string().describe("MCP server / platform id"),name:b.string().optional().describe("Display name (fallback for id-based lookup)")}).passthrough()).optional().describe("MCP server configs to resolve candidate namespaces from")}),Ss=[{method:"get",path:"/api/assistants",handler:K,validate:{query:q},openapi:{summary:"List assistants for the caller",description:"Returns all assistants owned by the authenticated user. An assistant binds a graph (skill), tools, prompt and routing rules into a runnable agent. `search` runs a hybrid lexical + semantic query (semantic_text field `search_semantic`).",tags:["assistants"]}},{method:"get",path:"/api/assistants/tags",handler:ns,openapi:{summary:"List distinct tags used across the caller's assistants",tags:["assistants"]}},{method:"get",path:"/api/assistants/:id",handler:ss,openapi:{summary:"Get an assistant by id",tags:["assistants"]}},{method:"post",path:"/api/assistants",handler:ts,validate:{body:ps},openapi:{summary:"Create an assistant",description:"Creates an assistant document in `.stkxp_assistants`. Required fields: `name`, `graphId`. Optional: `topic`, `description`, `tags`, `tools[]`, `llmRoutingRuleId`.",tags:["assistants"]}},{method:"put",path:"/api/assistants/:id",handler:es,openapi:{summary:"Update an assistant",tags:["assistants"]}},{method:"delete",path:"/api/assistants/:id",handler:as,openapi:{summary:"Delete an assistant",tags:["assistants"]}},{method:"post",path:"/api/assistants/namespace-options",handler:os,validate:{body:gs},openapi:{summary:"List candidate namespaces for assistant tool resolution",description:"Returns the set of namespaces the assistant's tools could resolve against, based on the platforms the caller has access to.",tags:["assistants"]}},{method:"post",path:"/api/assistants/:id/mcp-tools",handler:is,openapi:{summary:"Resolve the MCP tools an assistant would expose",description:"Computes the assistant's effective tool list at call time \u2014 useful for previewing what tools an assistant will see without actually running it.",tags:["assistants"]}},{method:"get",path:"/api/assistants/:id/mapping",handler:ds,openapi:{summary:"Get the assistant-to-package mapping (legacy)",tags:["assistants"]}},{method:"get",path:"/api/assistants/:id/token-projection",handler:us,openapi:{summary:"Theoretical single-pass max token usage for an assistant",description:"Resolves the assistant's graph (`assistant.graphId`), applies `assistant.llm_overrides[node.type]` on top of node-level routing rules, and returns the per-node `maxTokens` breakdown plus the summed single-pass max. Single-pass upper bound only \u2014 tool loops can exceed it.",tags:["assistants"],audience:"internal"}},{method:"get",path:"/api/assistants/:id/token-stats",handler:ms,openapi:{summary:"Aggregate this assistant's token usage across the caller's recent runs",description:"Reads `.stkxp_chats` filtered by `assistants.assistantId` (and `username` unless superuser) and sums the per-assistant `llm` token counts from each chat's `assistants[]` entry. Returns avg / max / p95 total tokens plus the last N runs.",tags:["assistants"],audience:"internal"}}];export{Ss as routes};
@@ -0,0 +1 @@
1
+ import{Client as I}from"@elastic/elasticsearch";import{z as m}from"zod";import v from"jsonwebtoken";import{randomUUID as R}from"crypto";import{config as A}from"../core/config";import{importAsyncApiSpec as _}from"../core/services/asyncapi-tools-service";import{getTrigger as T}from"../core/services/trigger-service";import{logWebhookCall as P,updateWebhookCall as h,sanitiseHeaders as S,hashPayload as x}from"../core/services/webhook-calls-service";import{dispatchInboundAsyncApi as $}from"../core/services/asyncapi-dispatch";import{driverManager as k}from"../core/services/asyncapi-drivers/driver-manager";const D=new I(A.elasticsearch),U=".stkxp_tools";function w(e){const t=e.auth?.username;if(t)return t;let o=e.cookies?.token;if(!o){const s=e.headers.authorization??"";o=s.startsWith("Bearer ")?s.slice(7):s||null}if(!o)return null;try{return v.decode(o)?.username??null}catch{return null}}function C(e){return!e||e.type==="none"?{}:e.type==="bearer"&&e.bearerToken?{Authorization:`Bearer ${e.bearerToken}`}:e.type==="basic"&&e.username?{Authorization:`Basic ${Buffer.from(`${e.username}:${e.password??""}`).toString("base64")}`}:e.type==="apiKey"&&e.apiKeyHeader&&e.apiKeyValue?{[e.apiKeyHeader]:e.apiKeyValue}:{}}const j=m.object({platformId:m.string().min(1),specUrl:m.string().url().optional(),specBody:m.string().optional()}).refine(e=>!!(e.specUrl||e.specBody),{message:"Provide specUrl or specBody (or both \u2014 specBody wins)."});async function B(e,t){const o=w(e);if(!o){t.status(401).json({error:"Unauthorized"});return}try{const s=j.parse(e.body),a=await _({...s,owner:o});for(const c of a.triggerIds??[])k.reconcileTrigger(c).then(i=>{i.ok?i.action!=="noop"&&console.log(`[asyncapi/import] reconcile ${c}: ${i.action}`):console.warn(`[asyncapi/import] reconcile ${c} failed: ${i.error}`)}).catch(i=>console.error(`[asyncapi/import] reconcile ${c} threw:`,i));t.json({success:!0,...a})}catch(s){if(s?.name==="ZodError"){t.status(400).json({success:!1,error:"Invalid body",issues:s.issues});return}console.error("[asyncapi/import] error:",s),t.status(500).json({success:!1,error:s?.message??String(s)})}}async function O(e,t){const o=w(e);if(!o){t.status(401).json({error:"Unauthorized"});return}const{toolName:s}=e.params;if(!s){t.status(400).json({success:!1,error:"toolName is required in the path"});return}let a;try{const p=await D.search({index:U,size:1,body:{query:{bool:{must:[{term:{name:s}},{term:{owner:o}},{term:{type:"asyncapi_publish"}}]}}}}),b=p?.hits?.hits?.[0]??p?.body?.hits?.hits?.[0];if(!b){t.status(404).json({success:!1,error:`Tool ${s} not found for this user`});return}a=b._source}catch(p){t.status(500).json({success:!1,error:`Tool lookup failed: ${p?.message??p}`});return}const c=e.body??{};if(typeof c!="object"||Array.isArray(c)){t.status(400).json({success:!1,error:"Request body must be a JSON object \u2014 it becomes the message payload."});return}const i=a.broker;if(!i?.host){t.status(500).json({success:!1,error:"Tool is missing broker.host configuration"});return}if(i.protocol!=="http"){t.status(501).json({success:!1,error:`Broker protocol "${i.protocol}" not implemented in V1 \u2014 only "http" gateway is supported.`});return}const y=i.channelStrategy??"path",n=i.host.replace(/\/+$/,""),l=a.channel;let r=n;const u={"Content-Type":"application/json",Accept:"application/json",...C(i.auth)};if(y==="path")r=`${n}/${encodeURIComponent(l)}`;else if(y==="query"){const p=new URL(n);p.searchParams.set("channel",l),r=p.toString()}else y==="header"&&(u["X-Channel"]=l);let d;try{d=await fetch(r,{method:"POST",headers:u,body:JSON.stringify(c)})}catch(p){t.status(502).json({success:!1,error:`Broker request failed: ${p?.message??p}`,url:r});return}const g=await d.text();let f;try{f=g?JSON.parse(g):void 0}catch{}if(!d.ok){t.status(d.status).json({success:!1,error:`Broker returned HTTP ${d.status}`,url:r,response:f??g});return}t.json({success:!0,toolName:s,channel:l,url:r,response:f??g??null})}async function N(e,t){const o=Date.now(),{triggerId:s}=e.params,a=R(),c=e.body??{},i=e.headers["x-forwarded-for"]||e.socket?.remoteAddress||null;if(await P({webhookCallId:a,receivedAt:new Date().toISOString(),teamId:"",triggerId:s??null,owner:null,sourceIp:i,status:"pending",payload:c,payloadHash:x(c),headers:S(e.headers)}),!s){await h(a,{status:"rejected_payload",rejectionReason:"missing_trigger_id",durationMs:Date.now()-o}),t.status(400).json({ok:!1,error:"triggerId is required in the path"});return}const y=typeof e.query.token=="string"&&e.query.token||typeof e.headers["x-webhook-secret"]=="string"&&e.headers["x-webhook-secret"]||null;if(!y){await h(a,{status:"rejected_token",rejectionReason:"secret_missing",durationMs:Date.now()-o}),t.status(401).json({ok:!1,error:"webhook secret required (query `token=` or header `X-Webhook-Secret`)"});return}let n;try{n=await T(s)}catch(u){await h(a,{status:"failed",error:`trigger lookup failed: ${u?.message??u}`,durationMs:Date.now()-o}),t.status(500).json({ok:!1,error:`trigger lookup failed: ${u?.message??u}`});return}if(!n){await h(a,{status:"rejected_payload",rejectionReason:"trigger_not_found",durationMs:Date.now()-o}),t.status(404).json({ok:!1,error:"trigger not found"});return}if(n.type!=="webhook"||!n.inputTemplate?.asyncapi){await h(a,{status:"rejected_payload",rejectionReason:"not_asyncapi_subscriber",durationMs:Date.now()-o}),t.status(404).json({ok:!1,error:"trigger is not an AsyncAPI subscriber"});return}if(!n.enabled){await h(a,{owner:n.owner??null,status:"rejected_team_disabled",rejectionReason:"trigger_disabled",durationMs:Date.now()-o}),t.status(423).json({ok:!1,error:"trigger is disabled"});return}if(n.webhookSecret!==y){await h(a,{owner:n.owner??null,status:"rejected_token",rejectionReason:"token_mismatch",durationMs:Date.now()-o}),t.status(403).json({ok:!1,error:"invalid webhook secret"});return}const l={};for(const[u,d]of Object.entries(e.headers))d!==void 0&&(l[u.toLowerCase()]=Array.isArray(d)?d.join(", "):String(d));const r=await $({trigger:n,payload:c,headers:l,source:i,webhookCallId:a});switch(r.kind){case"rejected":{const u=r.status==="rejected_quota"?429:r.status==="rejected_team_disabled"?423:400;t.status(u).json({ok:!1,error:r.message});return}case"accepted_no_target":{t.status(202).json({ok:!0,eventId:r.eventId,triggerId:n.id,channel:n.inputTemplate?.asyncapi?.channel,note:r.note});return}case"accepted":{t.status(202).json({ok:!0,eventId:r.eventId,triggerId:n.id,channel:n.inputTemplate?.asyncapi?.channel,runId:r.runId,chatId:r.chatId,teamId:r.teamId,...r.conversationId?{conversationId:r.conversationId,conversationTurn:r.conversationTurn}:{},message:"Accepted \u2014 team graph executing in the background."});return}case"failed":{t.status(500).json({ok:!1,error:r.message});return}}}const E=[{method:"post",path:"/api/asyncapi/import",handler:B,validate:{body:j},openapi:{summary:"Import an AsyncAPI spec and generate publish tools + subscriber triggers",description:'Parses the supplied spec (URL or raw body, JSON or YAML, AsyncAPI 3.x). `action: "send"` operations produce `.stkxp_tools` docs (type `asyncapi_publish`). `action: "receive"` operations produce `.stkxp_triggers` docs (type `webhook`) \u2014 each with a unique secret used by `/api/asyncapi/webhook/:triggerId`. Re-importing replaces both sets for the same platform.',tags:["asyncapi","tools"]}},{method:"post",path:"/api/asyncapi/query/:toolName",handler:O,openapi:{summary:"Invoke an `asyncapi_publish` tool by name",description:'Resolves the tool from `.stkxp_tools` (must be of type `asyncapi_publish` and owned by the caller), serialises the request body as the message payload, and POSTs it to the broker HTTP gateway. The channel is encoded per the tool\'s `broker.channelStrategy` (path | query | header). V1 supports `broker.protocol === "http"` only \u2014 native NATS/Kafka drivers come later.',tags:["asyncapi","tools"]}}],F=[{method:"post",path:"/api/asyncapi/webhook/:triggerId",handler:N,openapi:{summary:"Inbound webhook for an AsyncAPI subscriber trigger",description:"Public endpoint. Upstream systems POST a JSON payload here whenever the AsyncAPI subscribe channel fires. The handler validates the `?token=<webhookSecret>` (or `X-Webhook-Secret` header) against the trigger doc, durably stores the payload in `.stkxp_subscribed_events`, and bumps the trigger's execution counters. Returns 202 \u2014 graph execution of triggers is a separate chantier.",tags:["asyncapi","triggers"],security:"none"}},{method:"get",path:"/api/health/asyncapi-drivers",handler:async(e,t)=>{t.json(k.health())},openapi:{summary:"AsyncAPI V2.4 driver health snapshot",description:"Returns per-driver (http/nats/ws) liveness, active connection count, subscription count, last error string, plus a `subscriptions[]` array listing every live (platformId, triggerId, channel) pair currently subscribed in this process \u2014 used by ops dashboards to spot a stuck broker connection and to confirm that a trigger toggle / platform CRUD took effect without a PM2 restart.",tags:["asyncapi","health"],security:"none"}}];export{F as publicRoutes,E as routes};
@@ -0,0 +1 @@
1
+ import i from"zod";import w from"crypto";import{ElasticsearchWrapper as S}from"../core/services/elasticsearch-wrapper";import{config as k}from"../core/config";import{issueToken as j,authenticate as b,isUsernameExists as h,isEmailExists as f,getUserByEmail as v,registerUser as I,updateUser as g,deleteUser as D,userToken as p}from"../services/auth";import{sendMail as O,sendPasswordResetMail as U}from"../core/services/send_mail";const _=new S(k.elasticsearch,!0),x=i.object({username:i.string().describe("Account username"),password:i.string().describe("Account password")}),E=i.object({username:i.string().describe("Desired username (also becomes the default role)"),email:i.string().describe("Email address \u2014 a verification link is sent here"),password:i.string().describe("Initial password")}),R=i.object({username:i.string().describe("Target username (the caller)"),password:i.string().optional().describe("New password (requires currentPassword)"),currentPassword:i.string().optional().describe("Current password, verified before a password change"),email:i.string().optional().describe("New email"),roles:i.array(i.string()).optional().describe("Roles (defaults to existing roles)"),enabled:i.boolean().optional().describe("Enabled flag"),metadata:i.record(i.any()).optional().describe("Arbitrary user metadata to merge")}),T=i.object({preferences:i.record(i.any()).describe("Preferences object (locale, theme, \u2026) merged into user metadata")}),A=i.object({providers:i.record(i.any()).describe("Third-party identity providers configuration to store on the account")}),P=i.object({email:i.string().describe("Email to send the tokenised reset link to")}),z=i.object({token:i.string().describe("Reset token from the email link"),username:i.string().describe("Account username"),newPassword:i.string().describe("The new password to set")}),N=[{method:"post",path:"/api/auth/identify",validate:{},openapi:{summary:"Identify the caller from the session cookie",description:"Reads the `token` cookie and returns the decoded user (username/email/roles). Used by the SPA on boot to know who is logged in without re-authenticating.",tags:["auth"],security:"none"},handler:async function(r,e){const n=p(r.cookies.token);return n?e.json({body:{time:new Date().toISOString(),result:n}}):e.status(401).json({body:{time:new Date().toISOString(),result:{error:"Unauthorized"}}})}},{method:"post",path:"/api/auth/login",validate:{body:x},openapi:{summary:"Log in with username + password",description:"Authenticates the user and returns a JWT in the response body. Use the JWT as `Authorization: Bearer <token>` for all `/api/*` requests.",tags:["auth"],security:"none"},handler:async function(r,e){var n=r.body.username,a=r.body.password;if(!n||!a)return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"username and password are required"}}});const t=await b(n,a);if(console.log("authenticate response",r.body,t),t!==null&&typeof t=="object"&&t.username){console.log("resolve",t);const s=j(t.username,t.roles,t.enabled);console.log("token",s);try{console.log("issueToken response",s)}catch(o){return console.error("issueToken error",o),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}return e.json({body:{time:new Date().toISOString(),result:{token:s,username:t.username,roles:t.roles,enabled:t.enabled}}})}else return console.log("reject",t),e.status(401).json({body:{time:new Date().toISOString(),result:"Login failed"}});console.log("auth response",t)}},{method:"get",path:"/api/auth/check-availability",validate:{},openapi:{summary:"Check if a username/email is available for signup",tags:["auth"],security:"none"},handler:async function(r,e){const{username:n,email:a}=r.query,t={};if(n){const s=await h(n);(s?.body?.[n]??s?.[n])&&(t.username="Username already taken")}return a&&await f(a)&&(t.email="Email already registered"),e.json({body:{time:new Date().toISOString(),result:t}})}},{method:"post",path:"/api/auth/register",validate:{body:E},openapi:{summary:"Register a new user",description:"Creates a user account and sends a verification email. The user is inactive until they click the link served at `/verify-email`.",tags:["auth"],security:"none"},handler:async function(r,e){console.log("Registering user",r.body);const n=r.body.username,a=r.body.email,t=r.body.password;if(!n||!a||!t)return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"username, email and password are required"}}});const s=w.randomBytes(64).toString("hex");try{const o=await h(n);if(o?.body?.[n]??o?.[n])return e.status(409).json({body:{time:new Date().toISOString(),result:{error:"Username already taken"}}});if(await f(a))return e.status(409).json({body:{time:new Date().toISOString(),result:{error:"Email already registered"}}});const c=await I(n,a,t,s);return console.log("registerUser response",c),await O(n,a,s),e.status(200).json({body:{time:new Date().toISOString(),result:c}})}catch(o){return console.error("Register error:",o),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"put",path:"/api/auth/update",validate:{body:R},openapi:{summary:"Change the caller's password",description:"Requires `currentPassword` and `password`. Returns an error if the current password does not match.",tags:["auth"],security:"none"},handler:async function(r,e){console.log("Updating user",r.body);const{username:n,email:a,password:t,currentPassword:s,roles:o,enabled:u,metadata:m}=r.body;if(!n)return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"Username is required"}}});try{const c=await h(n),y=c?.body?.[n]??c?.[n];if(!y)return e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}});if(t&&s&&!await b(n,s))return e.status(401).json({body:{time:new Date().toISOString(),result:{error:"Current password is incorrect"}}});const d=o??y.roles??[],l=await g(n,a,t,d,u,m);return console.log("updateUser response",l),l instanceof Error||l?.meta?.statusCode>=400?(console.error("updateUser failed:",l),e.status(500).json({body:{time:new Date().toISOString(),result:{error:l?.message||"Failed to update user"}}})):e.status(200).json({body:{time:new Date().toISOString(),result:l}})}catch(c){return console.error("Error updating user:",c),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"delete",path:"/api/auth/user",validate:{},openapi:{summary:"Permanently delete the caller's account",description:"Cascades deletion across all `.stkxp_*` indices owned by the user (LLM configs, MCP servers, assistants, graphs, chats, tools, profiles). Irreversible.",tags:["auth"],security:"none"},handler:async function(r,e){const a=r.headers.authorization?.split(" ")[1]??(Array.isArray(r.headers["x-api-key"])?r.headers["x-api-key"][0]:r.headers["x-api-key"]),t=a?p(a):r.auth??null;return t?.username?await D(t.username)?e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0,message:"Account deleted successfully"}}}):e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Failed to delete account"}}}):e.status(401).json({body:{time:new Date().toISOString(),result:{error:"Unauthorized"}}})}},{method:"put",path:"/api/auth/preferences",validate:{body:T},openapi:{summary:"Update the caller's preferences (locale, theme, \u2026)",tags:["auth"],security:"none"},handler:async function(r,e){const a=r.headers.authorization?.split(" ")[1]??(Array.isArray(r.headers["x-api-key"])?r.headers["x-api-key"][0]:r.headers["x-api-key"]),t=a?p(a):r.auth??null;if(!t?.username)return e.status(401).json({body:{time:new Date().toISOString(),result:{error:"Unauthorized"}}});const{preferences:s}=r.body;if(!s||typeof s!="object")return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"preferences object is required"}}});try{const o=await h(t.username),u=o?.body?.[t.username]??o?.[t.username];if(!u)return e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}});const m=u.metadata||{},c=Object.keys(m).filter(d=>!d.startsWith("_")).reduce((d,l)=>(d[l]=m[l],d),{}),y=await g(t.username,void 0,void 0,u.roles,void 0,{...c,preferences:s});return e.status(200).json({body:{time:new Date().toISOString(),result:y}})}catch(o){return console.error("Error saving preferences:",o),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"put",path:"/api/auth/update-providers",validate:{body:A},openapi:{summary:"Update third-party identity providers linked to the account",tags:["auth"],security:"none"},handler:async function(r,e){console.log("Updating user providers",r.body);const a=r.headers.authorization?.split(" ")[1]??(Array.isArray(r.headers["x-api-key"])?r.headers["x-api-key"][0]:r.headers["x-api-key"]),t=a?p(a):r.auth??null;if(!t||!t.username)return e.status(401).json({body:{time:new Date().toISOString(),result:{error:"Unauthorized"}}});const{providers:s}=r.body;if(!s)return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"Providers configuration is required"}}});try{const o=await h(t.username);console.log("PUT /providers - userExists:",o);const u=o.body?.[t.username]||o[t.username];if(!u)return e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}});const m=u.metadata||{},c=Object.keys(m).filter(d=>!d.startsWith("_")).reduce((d,l)=>(d[l]=m[l],d),{}),y=await g(t.username,void 0,void 0,u.roles,void 0,{...c,providers:s});return console.log("updateUser providers response",y),e.status(200).json({body:{time:new Date().toISOString(),result:y}})}catch(o){return console.error("Error updating user providers:",o),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"get",path:"/api/auth/user/:username",validate:{},openapi:{summary:"Fetch a user profile by username",tags:["auth"],security:"none"},handler:async function(r,e){const a=r.headers.authorization?.split(" ")[1]??(Array.isArray(r.headers["x-api-key"])?r.headers["x-api-key"][0]:r.headers["x-api-key"]),t=a?p(a):r.auth??null;if(console.log("GET /user/:username - User from token:",t),!t||!t.username)return e.status(401).json({body:{time:new Date().toISOString(),result:{error:"Unauthorized"}}});const{username:s}=r.params;if(s!==t.username&&!t.roles?.includes("superuser"))return e.status(403).json({body:{time:new Date().toISOString(),result:{error:"Forbidden - You can only access your own data"}}});try{const o=await h(s);console.log("GET /user/:username - userExists:",o);const u=o.body?.[s]||o[s];return u?(console.log("GET /user/:username - Found user:",u),e.status(200).json({body:{time:new Date().toISOString(),result:{[s]:u}}})):(console.error("GET /user/:username - User not found in ES:",s),e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}}))}catch(o){return console.error("Error getting user:",o),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"post",path:"/api/auth/forgot-password",validate:{body:P},openapi:{summary:"Request a password reset email",description:"Sends a tokenised reset link to the email associated with the supplied username. Always returns 200 even when the user is unknown (prevents enumeration).",tags:["auth"],security:"none"},handler:async function(r,e){const{email:n}=r.body;if(!n)return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"Email is required"}}});try{const a=await v(n);if(!a)return console.log(`[forgot-password] No user found for email: ${n}`),e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0}}});const{username:t,userRecord:s}=a,o=w.randomBytes(32).toString("hex"),u=new Date(Date.now()+3600*1e3).toISOString(),m=s.metadata||{},c=Object.keys(m).filter(y=>!y.startsWith("_")).reduce((y,d)=>(y[d]=m[d],y),{});return await g(t,void 0,void 0,s.roles,void 0,{...c,resetToken:o,resetTokenExpiresAt:u}),await U(t,n,o),e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0}}})}catch(a){return console.error("Forgot password error:",a),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"post",path:"/api/auth/reset-password",validate:{body:z},openapi:{summary:"Complete a password reset using a token",description:"Requires `username`, `token` (from the email link) and the new `password`.",tags:["auth"],security:"none"},handler:async function(r,e){const{token:n,username:a,newPassword:t}=r.body;if(!n||!a||!t)return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"token, username and newPassword are required"}}});try{const s=await h(a),o=s?.body?.[a]??s?.[a];if(!o)return e.status(404).json({body:{time:new Date().toISOString(),result:{error:"User not found"}}});const{resetToken:u,resetTokenExpiresAt:m}=o.metadata||{};if(!u||u!==n)return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"Invalid or expired reset token"}}});if(!m||new Date>new Date(m))return e.status(400).json({body:{time:new Date().toISOString(),result:{error:"Reset token has expired"}}});const c=o.metadata||{},y=Object.keys(c).filter(d=>!d.startsWith("_")&&d!=="resetToken"&&d!=="resetTokenExpiresAt").reduce((d,l)=>(d[l]=c[l],d),{});return await g(a,void 0,t,void 0,void 0,y),e.status(200).json({body:{time:new Date().toISOString(),result:{success:!0}}})}catch(s){return console.error("Reset password error:",s),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}},{method:"get",path:"/api/auth/providers",validate:{},openapi:{summary:"List supported third-party auth providers",tags:["auth"],security:"none"},handler:async function(r,e){const a=r.headers.authorization?.split(" ")[1]??(Array.isArray(r.headers["x-api-key"])?r.headers["x-api-key"][0]:r.headers["x-api-key"]),t=a?p(a):r.auth??null;if(console.log("GET /providers - User from token:",t),!t||!t.username)return e.status(401).json({body:{time:new Date().toISOString(),result:{error:"Unauthorized"}}});try{const s=await h(t.username);console.log("GET /providers - userExists:",s);const o=s.body?.[t.username]||s[t.username];if(!o)return console.error("GET /providers - User not found in ES:",t.username),e.status(200).json({body:{time:new Date().toISOString(),result:{providers:null}}});const u=o.metadata?.providers||null;return console.log("GET /providers - Found providers:",u),e.status(200).json({body:{time:new Date().toISOString(),result:{providers:u}}})}catch(s){return console.error("Error getting user providers:",s),e.status(500).json({body:{time:new Date().toISOString(),result:{error:"Internal server error"}}})}}}];export{N as routes};