@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,16 @@
1
+ import{interrupt as j}from"@langchain/langgraph";import{AIMessage as P}from"@langchain/core/messages";import{DynamicStructuredTool as U}from"@langchain/core/tools";import{z as T}from"zod";import{createLLMInstance as z}from"../../../llm/providers";import{runInSandbox as V}from"../reasoning/code-executor/sandbox";import{fetchResources as W}from"../reasoning/code-executor/resource-bridge";import{buildAvailableTools as X,buildAvailableResources as q}from"../../utils/sandbox-catalog";const K=5e3,Y=64;async function Q(o,e,$,u){if(o==null)return null;if(typeof o!="string")return o;const p=o.trim();if(!p)return null;try{return JSON.parse(p)}catch{}const b=X($.tools??[]),g=($.assistant?.resources_policy?.resources||[]).map(f=>f?.id).filter(Boolean),A=g.length>0||$.username?await W($.username??"",g):[],m=q(A),d=await V({scriptBody:p,hostFunctions:[],timeoutMs:K,maxMemoryMb:Y,extraGlobals:{context:e,availableTools:b,availableResources:m}});if(d.consoleLogs.length>0){const f=`[human_approval:${u}:${e.threadId??"?"}]`;for(const i of d.consoleLogs)console.log(`${f} ${i}`)}return d.ok?d.value??null:(console.warn(`[human_approval] form_schema script failed (${d.error?.kind}): ${d.error?.message}`),null)}const J=T.object({shouldInterrupt:T.boolean().describe("Whether to interrupt the graph and ask for human approval"),message:T.string().describe("Clear, concise message shown to the user in the approval dialog"),details:T.string().optional().describe("Additional context or technical details about the action"),type:T.string().optional().describe("Interrupt type: approval | form")});async function ie(o,e){const{HumanMessage:$}=await import("@langchain/core/messages"),u=e.graphDef?.nodes?.find(n=>n.id===e.nodeId)||{},p=`${e.nodeId}_approved`,b=u.interrupt_message??"Valider cette action ?",g=u.interrupt_type??"approval",A=u.interrupt_payload_fields??["topic"],m=!!u.always_interrupt,d=u.instructions??"",f=u.form_schema??null,i=await Q(f,{topic:o?.topic,userContext:o?.userContext,threadId:o?.threadId,namespaceMap:o?.namespaceMap??{},customFields:o?.customFields??{}},{tools:e.tools,assistant:e.assistant,username:e.username},e.nodeId),y={};for(const n of A)o[n]!==void 0&&(y[n]=o[n]);const c=[...o.messages??[]].reverse().find(n=>n._getType?.()==="human"||n.role==="human");c&&(y.lastMessage=typeof c.content=="string"?c.content:c.content?.[0]?.text??"");let L=b,k,O=g;if(!m&&e.llmConfig&&d)try{const n=await Z(o,y,d,e.llmConfig);if(!n.shouldInterrupt)return console.log(`[human_approval:${e.nodeId}] LLM gate \u2192 shouldInterrupt=false, continuing`),{customFields:{[p]:!0}};L=n.message||b,k=n.details,O=g!=="approval"?g:n.type||g,console.log(`[human_approval:${e.nodeId}] LLM gate \u2192 interrupting: "${L}"`)}catch(n){console.warn(`[human_approval:${e.nodeId}] LLM gate failed, falling back to static message: ${n?.message}`)}else console.log(`[human_approval:${e.nodeId}] ${m?"always_interrupt=true":"no LLM config/instructions"}, using static message`);let E=y;if(O==="form"&&i){const n=i.tool_prefill??[],v=(t,s)=>s.split(".").reduce((a,l)=>a?.[l],t),S={};if(n.length>0){for(const t of o.messages??[])if((t._getType?.()??t.role)==="tool")try{const s=JSON.parse(typeof t.content=="string"?t.content:JSON.stringify(t.content));for(const a of n)if(a.path!==void 0){const l=v(s,a.path);l!=null&&(S[a.to]=l)}else if(a.collect!==void 0){const l=a.array_path?v(s,a.array_path):Array.isArray(s)?s:null;if(Array.isArray(l)){const I=l.map(M=>M[a.collect]).filter(Boolean);I.length>0&&(S[a.to]=I)}}}catch{}}const r={},_=[...o.messages??[]].filter(t=>{const s=typeof t.content=="string"?t.content:"";return(t._getType?.()==="human"||t.role==="human")&&s.startsWith("[Form data submitted]")});if(_.length>0){const t=_[_.length-1],s=typeof t.content=="string"?t.content:"";try{const a=s.replace(`[Form data submitted]
2
+ `,"");Object.assign(r,JSON.parse(a))}catch{}}const N=i.terminal_errors??[];let w=i.description??k,R=null;const F=o.messages??[];for(let t=F.length-1;t>=0;t--){const s=F[t];if((s._getType?.()??s.role)==="tool")try{const a=JSON.parse(typeof s.content=="string"?s.content:JSON.stringify(s.content));if(a?.error==="TOOL_EXECUTION_FAILED"&&a?.error_message){let l=a.error_message,I;try{const M=JSON.parse(l);I=M?.code;const B=M?.fields;if(B?.length){const H=B.map(C=>`\u2022 ${C.path} : ${C.message} (${C.code})`).join(`
3
+ `);l=`${M.message??M.code??"Erreur API"}
4
+
5
+ ${H}`}else M?.message&&(l=M.message)}catch{}I&&N.includes(I)?(R=l,console.log(`[human_approval:${e.nodeId}] Terminal error detected (${I}), aborting form retry`)):w=`\u26A0\uFE0F Erreur lors de la soumission pr\xE9c\xE9dente :
6
+ ${l}
7
+
8
+ Corrigez les champs et soumettez \xE0 nouveau.`;break}}catch{}}if(R!==null)return{messages:[new P(`\u274C Impossible de finaliser l'enregistrement :
9
+
10
+ ${R}`)],customFields:{[p]:!1}};const D={...S,...r},G=(i.fields??[]).map(t=>{const s=D[t.name];return s!==void 0?{...t,value:s}:t});E={type:"form",tool:u.id??e.nodeId,title:i.title??L,description:w,submitLabel:i.submitLabel,fields:G}}const h=j({type:O,message:L,details:k,payload:E});if(process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][HUMAN-APPROVAL]: "+JSON.stringify(o)),!h?.approved){const n=h?.comment?` Motif : ${h.comment}`:"";return{messages:[new P(`Action annul\xE9e par l'utilisateur.${n}`)],customFields:{[p]:!1}}}if(O==="form"&&h.values&&Object.keys(h.values).length>0){const n=JSON.stringify(h.values,null,2);console.log(`[human_approval:${e.nodeId}] Form submitted with values:`,n);const v={},S=Array.isArray(i?.writeToState)?i.writeToState:[];for(const r of S){const _=h.values[r.field];if(_==null||_==="")continue;const N=r.shape==="namespaceBinding"?[{namespace:String(_),platformId:"user-provided",platformName:"(manuel)"}]:_;if(r.keyBy){const w=h.values[r.keyBy]??o[r.keyBy]??e.defaultSystem;if(!w){console.warn(`[human_approval:${e.nodeId}] writeToState: no key for rule field="${r.field}" channel="${r.channel}" (keyBy="${r.keyBy}", no defaultSystem) \u2014 skipping`);continue}v[r.channel]={...v[r.channel]||{},[String(w).toLowerCase()]:N}}else v[r.channel]=N;console.log(`[human_approval:${e.nodeId}] writeToState \u2192 ${r.channel}${r.keyBy?`[${r.keyBy}]`:""} from field "${r.field}"`)}return v.customFields={...v.customFields||{},[p]:!0,[`${e.nodeId}_formValues`]:h.values},{...v,messages:[new $(`[Form data submitted]
11
+ ${n}`)]}}return{customFields:{[p]:!0}}}async function Z(o,e,$,u){const p=z({...u,streaming:!1,temperature:0}),b=new U({name:"extract",description:"Extract the approval gate decision.",schema:J,func:async()=>"ok"}),g=p.bindTools([b],{tool_choice:{type:"tool",name:"extract"}}).withConfig({tags:["nostream"]}),A=(o.messages??[]).filter(c=>c._getType?.()==="tool"||c.role==="tool").slice(-3).map(c=>(typeof c.content=="string"?c.content:JSON.stringify(c.content)).slice(0,500)),m=[];e.lastMessage&&m.push(`User request: ${e.lastMessage}`),A.length>0&&m.push(`Recent tool results:
12
+ ${A.join(`
13
+ ---
14
+ `)}`),e.topic&&m.push(`Topic: ${e.topic}`);const d=m.join(`
15
+
16
+ `)||"No additional context.",f=await g.invoke([{role:"system",content:$},{role:"user",content:d}]),i=f?.tool_calls?.find(c=>c.name==="extract");if(!i)throw console.error(`[human_approval] callApprovalGateLLM: no "extract" tool call in response. content=${JSON.stringify(f?.content)} tool_calls=${JSON.stringify(f?.tool_calls)}`),new Error('No "extract" tool call returned by the LLM gate (see raw AIMessage logged above)');const y=J.safeParse(i.args);if(!y.success)throw console.error(`[human_approval] callApprovalGateLLM: tool call args failed schema validation. args=${JSON.stringify(i.args)} issues=${JSON.stringify(y.error.issues)}`),new Error(`LLM gate tool call args failed schema validation: ${y.error.message}`);return y.data}export{ie as execute};
@@ -0,0 +1 @@
1
+ import{execute as e}from"./control/check-reset";import{execute as t}from"./control/topic-detection";import{execute as o}from"./reasoning/system";import{execute as r}from"./reasoning/tool-executor";import{execute as x}from"./reasoning/code-executor";import{execute as c}from"./reasoning/static-code-executor";import{execute as m}from"./tools/tool";import{execute as u}from"./tools/tool-invoker";import{execute as a}from"./tools/raw-output";import{execute as s}from"./context/state-setter";import{execute as i}from"./tools/tool-cleaner";import{execute as p}from"./reasoning/local-extractor";import{execute as f}from"./reasoning/response-generator";import{execute as n}from"./context/compare-context";import{execute as l}from"./context/enrich-context";import{execute as C}from"./governance/human-approval";import{execute as T}from"./context/inventory-context";import{execute as S}from"./context/skills-context";import{execute as v}from"./context/node-types-context";import{execute as R}from"./context/relevant-skills-context";import{execute as d}from"./context/relevant-assistants-context";import{execute as k}from"./context/assistants-context";import{execute as E}from"./context/namespace-context";import{execute as y}from"./orchestration/team-pipeline";import{execute as A}from"./orchestration/team-parallel";import{execute as I}from"./orchestration/team-decider";import{execute as g}from"./orchestration/team-router";import{execute as h}from"./orchestration/team-invoker";import{execute as D}from"./orchestration/team-finder";import{execute as G}from"./orchestration/suggestion-generator";export{k as executeAssistantsContext,e as executeCheckReset,x as executeCodeExecutor,n as executeCompareContext,l as executeEnrichContext,C as executeHumanApproval,T as executeInventoryContext,p as executeLocalExtractor,E as executeNamespaceContext,v as executeNodeTypesContext,a as executeRawOutput,d as executeRelevantAssistantsContext,R as executeRelevantSkillsContext,f as executeResponseGenerator,S as executeSkillsContext,s as executeStateSetter,c as executeStaticCodeExecutor,G as executeSuggestionGenerator,o as executeSystem,I as executeTeamDecider,D as executeTeamFinder,h as executeTeamInvoker,A as executeTeamParallel,y as executeTeamPipeline,g as executeTeamRouter,m as executeTool,i as executeToolCleaner,r as executeToolExecutor,u as executeToolInvoker,t as executeTopicDetection};
@@ -0,0 +1,17 @@
1
+ import{dispatchCustomEvent as f}from"@langchain/core/callbacks/dispatch";import{z as i}from"zod";import{createLLMInstance as y}from"../../../llm/providers";import{contentToString as w}from"../../utils/content-utils";const b=i.object({suggestions:i.array(i.string()).min(1).max(3).describe("1 to 3 short, natural-language follow-up messages the user might send next.")}),I=`You just delivered the answer below to a user. Propose 1 to 3 short, natural follow-up messages the user might plausibly send next.
2
+
3
+ Rules:
4
+ - Write each suggestion as if the USER is typing it (first person, a question or request) \u2014 not as a description of what will happen.
5
+ - Never mention team names, assistant names, or any internal identifier \u2014 a suggestion must read like a normal thing a person would type in a chat box.
6
+ - If a candidate below is a clearly better fit for a suggestion's topic, phrase that suggestion so that re-sending it would naturally lead there \u2014 but keep the phrasing generic and user-facing.
7
+ - If no candidates are relevant, still propose at least one plausible on-topic follow-up based on the answer alone.
8
+ - Keep each suggestion under 100 characters.`,S=new Set(["web","embed",void 0]);async function j(u,m){const{llmConfig:g,deps:t,searchTeams:c}=m;if(!S.has(t.channel))return{};const d=[...u.messages||[]].reverse().find(e=>e._getType?.()==="ai"||e.constructor?.name==="AIMessage");let s=w(d).trim();if(!s){const a=[...u.teamAssistantResults||[]].reverse().find(r=>r.success&&r.output);s=typeof a?.output=="string"?a.output.trim():""}if(!s)return{};let n=[];if(t.username)try{n=await c({owner:t.username,query:s,k:3,excludeTeamId:t.teamId})}catch{n=[]}const l=(t.teamAssistants||[]).map(e=>({name:e?.name||e?.assistantId||"unknown"})),p=[n.length>0?`Other teams (semantically related to this answer):
9
+ ${n.map(e=>`- ${e.name}${e.description?` \u2014 ${e.description}`:""}`).join(`
10
+ `)}`:"",l.length>0?`Other assistants in this same team:
11
+ ${l.map(e=>`- ${e.name}`).join(`
12
+ `)}`:""].filter(Boolean).join(`
13
+
14
+ `),h=[`Answer just delivered:
15
+ ${s}`,p].filter(Boolean).join(`
16
+
17
+ `);try{const e=y(g);if(!e?.withStructuredOutput)return{};const o=(await e.withStructuredOutput(b).withConfig({tags:["nostream"]}).invoke([{role:"system",content:I},{role:"user",content:h}]))?.suggestions;if(!Array.isArray(o)||o.length===0)return{};await f("chat_suggestions",{suggestions:o})}catch(e){console.error("[suggestion_generator] failed, no-op:",e?.message??e)}return{}}export{j as execute};
@@ -0,0 +1 @@
1
+ import{AIMessage as R}from"@langchain/core/messages";import{dispatchCustomEvent as D}from"@langchain/core/callbacks/dispatch";import{logNodeExecution as E}from"../../utils/logging-utils";import{resolveTeamAssistants as T,stampResultsWithTurnIndex as w}from"./team-execution/team-assistant-utils";import{runStandaloneTeamAssistants as _}from"./team-execution/decider-standalone-runner";import{buildAllFailedErrorMessage as S}from"./team-execution/decider-error";import{runDeciderSynthesis as C}from"./team-execution/decider-synthesis";async function L(s,f){const{llmConfig:o,graphDef:c,cfg:g,assistant:p,teamAssistants:i,buildAssistantApp:r,deps:A,nodeDef:y}=f;process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TEAM-DECIDER]: "+JSON.stringify(s));const{teamAssistants:t,effectiveIds:h,filterSource:l}=T(i,y,s);l&&i&&t&&console.log(`[team_decider] ${l} filter (standalone mode only): ${t.length}/${i.length} candidates (configured: [${h.join(", ")}])`);const m=g?.signal;E("TEAM_DECIDER",o,{assistantResults:s.teamAssistantResults?.length??0});let e=s.teamAssistantResults||[],a=null;if(await D("team_event",{node:"team_decider",kind:"decider_start",priorResults:e.length,standalone:e.length===0&&(t?.length??0)>0}),e.length===0&&t&&t.length>0&&r&&(a=await _({teamAssistants:t,buildAssistantApp:r,deps:A,abortSignal:m,state:s}),e=a),e.length===0)return console.warn("[team_decider] No assistant results to synthesise"),{messages:[]};const d=e.filter(n=>n.success&&n.output);if(d.length===0){console.warn("[team_decider] All assistants failed \u2014 surfacing the failure reason to the chat instead of an empty response");const n=await S(e);return{messages:[new R({content:n})]}}const u=await C({state:s,llmConfig:o,graphDef:c,assistant:p,successfulResults:d,abortSignal:m});if(a&&a.length>0){const n=w(s.teamAssistantResultsHistory??[],a);return{messages:[u],teamAssistantResultsHistory:n}}return{messages:[u]}}export{L as execute};
@@ -0,0 +1,4 @@
1
+ import{dispatchCustomEvent as i}from"@langchain/core/callbacks/dispatch";function s(r){if(typeof r!="string"||!r.trim())return"Erreur inconnue (aucun d\xE9tail fourni par l'assistant).";const o=r.match(/\{[\s\S]*\}/);if(o)try{const e=JSON.parse(o[0]),n=e?.error?.message??e?.message;if(typeof n=="string"&&n.trim())return n.trim()}catch{}return r.replace(/^Error:\s*/,"").trim().slice(0,500)}async function c(r){const e={type:"markdown",title:"\u26A0\uFE0F Aucun assistant n'a pu r\xE9pondre",body:`Les assistant(s) suivant(s) ont \xE9chou\xE9 :
2
+
3
+ ${r.map(t=>`- **${t.assistantName}** \u2014 ${s(t.output)}`).join(`
4
+ `)}`},n=JSON.stringify(e);return await i("decider_direct_block",{node:"team_decider",kind:"decider_error",ndjson:n,failedCount:r.length}),n}export{c as buildAllFailedErrorMessage,s as humanizeAssistantError};
@@ -0,0 +1 @@
1
+ import{HumanMessage as N}from"@langchain/core/messages";import{dispatchCustomEvent as c}from"@langchain/core/callbacks/dispatch";import{extractAssistantOutput as x}from"../../../utils/message-utils";async function D(T){const{teamAssistants:a,buildAssistantApp:y,deps:A,abortSignal:m,state:d}=T,f=A.threadId;console.log(`[team_decider] No prior results \u2014 running ${a.length} assistants sequentially`);const e=d.messages.find(t=>t._getType?.()==="human"||t.constructor?.name==="HumanMessage"),S=typeof e?.content=="string"?e.content:e?.content?.[0]?.text??"",_={messages:[new N({content:[{type:"text",text:S}]})],namespaceMap:d.namespaceMap},n=[];for(let t=0;t<a.length;t++){if(m?.aborted){console.log(`[team_decider] \u{1F6D1} Aborted by user \u2014 stopping after ${t}/${a.length} assistants`);break}const s=a[t],u=`${f}-ta-${t}`,p=Date.now();await c("assistant_start",{assistantId:s.assistantId,assistantName:s.name,index:t,total:a.length,subThreadId:u});try{const h=(await y(s,t)).invoke(_,{configurable:{thread_id:u,checkpoint_ns:""},recursionLimit:100,signal:m}),w=new Promise(($,M)=>setTimeout(()=>M(new Error("Assistant timeout after 180000ms")),18e4)),l=await Promise.race([h,w]),b=l?.messages||[],r=x(b),g=l?.toolsUsedAccum||[],I=Date.now()-p;await c("assistant_end",{assistantId:s.assistantId,assistantName:s.name,success:!0,durationMs:I,toolsUsed:g,output:typeof r=="string"?r.slice(0,1500):""}),n.push({assistantId:s.assistantId,assistantName:s.name,output:r,toolsUsed:g,success:!0,durationMs:I})}catch(o){const i=Date.now()-p;console.error(`[team_decider] Assistant ${s.name} failed:`,o.message),await c("assistant_end",{assistantId:s.assistantId,assistantName:s.name,success:!1,durationMs:i,toolsUsed:[]}),n.push({assistantId:s.assistantId,assistantName:s.name,output:`Error: ${o.message}`,toolsUsed:[],success:!1,durationMs:i})}}return n}export{D as runStandaloneTeamAssistants};
@@ -0,0 +1,29 @@
1
+ import{SystemMessage as N,HumanMessage as T,AIMessage as O}from"@langchain/core/messages";import{dispatchCustomEvent as m}from"@langchain/core/callbacks/dispatch";import{createLLMInstance as k}from"../../../../llm/providers";import{getNodeInstructions as E,extractCrossTurnHistory as M}from"../../../utils/message-utils";import{findLatestHumanMessageText as R}from"./team-assistant-utils";const $=`You are a synthesis expert. Multiple specialist assistants have analysed the same question, and their outputs are provided in [Specialist outputs] below.
2
+
3
+ Your task is to produce a single, comprehensive, non-redundant final response that:
4
+ 1. Integrates all findings from the specialists
5
+ 2. Resolves any contradictions with a clear rationale
6
+ 3. Highlights the most actionable insights
7
+ 4. Does NOT simply concatenate the outputs \u2014 synthesise them into a unified analysis
8
+
9
+ \u26A0\uFE0F RESPONSE FORMAT \u2014 NDJSON ONLY (newline-delimited JSON):
10
+ - Each line of your response must be a valid standalone JSON object \u2014 one block per line.
11
+ - DO NOT wrap your response in {"type":"dashboard","blocks":[...]} \u2014 emit the blocks directly, one per line.
12
+ - DO NOT wrap with markdown code fences (no \`\`\`json fences).
13
+ - Allowed block types: {"type":"markdown","title":"...","body":"..."} | {"type":"echarts","title":"...","options":{...}} | {"type":"table","title":"...","columns":[...],"data":[...]} | {"type":"eui","title":"...","body":"..."}
14
+ - Start your very first character with the opening { of the first block. No preamble.
15
+
16
+ Example (literal \u2014 newline between objects, no array, no wrapper):
17
+ {"type":"markdown","title":"Summary","body":"..."}
18
+ {"type":"table","title":"Comparison","columns":[...],"data":[...]}`;async function P(d){const{state:r,llmConfig:n,graphDef:u,assistant:h,successfulResults:t,abortSignal:o}=d,y=await E(u,"team_decider",$,h),l=3e3,g=(n?.maxTokens??0)*4,f=Math.max(1,t.length),c=Math.max(l,Math.floor(g/f));console.log(`[team_decider] \u{1F4D0} Per-specialist context cap: ${c} chars (routing rule "${n?.routingRuleName??"?"}" maxTokens=${n?.maxTokens??"?"}, ${t.length} specialist(s), floor=${l})`);const p=t.map(e=>`### ${e.assistantName}
19
+ ${e.output.substring(0,c)}`).join(`
20
+
21
+ ---
22
+
23
+ `),a=M(r.messages,{maxTurns:3}),b=a?`
24
+
25
+ ${a}`:"",w=R(r.messages,"Synthesise the findings."),x=k(n),C=[new N(`${y}${b}
26
+
27
+ [Specialist outputs]
28
+
29
+ ${p}`),new T({content:[{type:"text",text:w}]})];await m("team_event",{node:"team_decider",kind:"decider_synthesis_start",specialistCount:t.length,contextChars:p.length,priorTurnsInjected:a?a.length:0,specialists:t.map(e=>e.assistantName)});let s="";const S=await x.stream(C,{signal:o});for await(const e of S){if(o?.aborted){console.log(`[team_decider] \u{1F6D1} Synthesis aborted by user after ${s.length} chars`);break}const _=typeof e.content=="string"?e.content:Array.isArray(e.content)?e.content.map(i=>typeof i=="string"?i:i?.text??"").join(""):"";s+=_}return console.log(`[team_decider] \u2705 Synthesis complete (${t.length} inputs merged, ${s.length} chars)`),await m("team_event",{node:"team_decider",kind:"decider_synthesis_end",outputChars:s.length,aborted:o?.aborted??!1}),new O({content:s})}export{$ as DEFAULT_DECIDER_PROMPT,P as runDeciderSynthesis};
@@ -0,0 +1,2 @@
1
+ import{dispatchCustomEvent as i}from"@langchain/core/callbacks/dispatch";import{saveMemoryDoc as p,setLastChatTraceId as c}from"../../../../services/memories-service";async function v(m){const{results:o,deps:t,nodeDef:u,originalText:d}=m;if(!(!(u?.autoSaveMemory!==!1)||!t.username||!o.some(e=>e.success&&e.output)))try{const e=o.filter(s=>s.success&&s.output).map(s=>`[${s.assistantName}] ${String(s.output).substring(0,500)}`).join(`
2
+ `),r=t.rawUserInput??d,n=((r?`User asked: "${r.substring(0,200)}". `:"")+"Team findings: "+e).substring(0,2500),a=await p({owner:t.username,text:n,memoryType:"chat_trace",salience:.2,tags:["team","auto-save"],teamId:t.teamId??null,sourceChatId:t.chatId??null});a&&(t.chatId&&c(t.chatId,a.id),console.log(`[team_pipeline] Auto-saved memory ${a.id} for ${t.username}`),await i("team_event",{node:"team_pipeline",kind:"pipeline_memory_saved",memoryId:a.id,textChars:n.length}))}catch(e){console.error("[team_pipeline] Auto-save memory failed:",e?.message??e),await i("team_event",{node:"team_pipeline",kind:"pipeline_memory_save_failed",error:String(e?.message??e).slice(0,200)})}}export{v as autoSaveTeamPipelineMemory};
@@ -0,0 +1,7 @@
1
+ import{HumanMessage as x}from"@langchain/core/messages";import{dispatchCustomEvent as r}from"@langchain/core/callbacks/dispatch";import{evaluateCondition as S}from"../../../../utils/condition-evaluator";import{extractLastToolResultJson as k,extractAssistantOutput as v}from"../../../utils/message-utils";async function C(b){const{teamAssistants:e,buildAssistantApp:I,deps:g,abortSignal:d,contextTemplate:w,historyPrefix:h,originalText:c,namespaceMap:f,topic:_}=b,p=[];let $,y={messages:[new x({content:[{type:"text",text:`${h}${c}`}]})],namespaceMap:f};const T=Date.now();for(let s=0;s<e.length;s++){if(d?.aborted){console.log(`[team_pipeline] \u{1F6D1} Aborted by user \u2014 stopping after ${s}/${e.length} assistants`);break}const t=e[s];if(!t.runAlways&&t.condition&&!await S(t.condition,{topic:_,userMessage:c,lastResult:$})){console.log(`[team_pipeline] \u23ED\uFE0F Skipping "${t.name}" \u2014 condition not met: "${t.condition}"`),await r("assistant_skipped",{assistantId:t.assistantId,assistantName:t.name,index:s,total:e.length,condition:t.condition,reason:"condition_not_met"});continue}const A=`${g.threadId}-ta-${s}-${T}`,N=Date.now();console.log(`[team_pipeline] DEBUG: invoking assistant ${t.name} with threadId=${A}`),await r("assistant_start",{assistantId:t.assistantId,assistantName:t.name,index:s,total:e.length,subThreadId:`${g.threadId}-ta-${s}`}),await r("assistant_progress",{assistantId:t.assistantId,assistantName:t.name,phase:"running",index:s,total:e.length,message:`Assistant ${s+1}/${e.length} running: ${t.name}`});let l="",i=[],o=!0,u=[];try{const a=await(await I(t,s)).invoke(y,{configurable:{thread_id:A,checkpoint_ns:""},recursionLimit:100,signal:d});u=a?.messages||[],l=v(u),i=a?.toolsUsedAccum||[]}catch(n){o=!1;const a=n?.name==="AbortError"||d?.aborted===!0||/aborted/i.test(String(n?.message??""));l=a?"Cancelled by user":`Error: ${n.message}`,a?console.log(`[team_pipeline] \u{1F6D1} Assistant ${t.name} cancelled by user`):console.error(`[team_pipeline] Assistant ${t.name} failed:`,n.message)}const m=Date.now()-N;if(p.push({assistantId:t.assistantId,assistantName:t.name,output:l,toolsUsed:i,success:o,durationMs:m}),o&&($=k(u)),await r("assistant_progress",{assistantId:t.assistantId,assistantName:t.name,phase:o?"completed":"failed",index:s,total:e.length,durationMs:m,toolsUsed:i,message:o?`Assistant ${s+1}/${e.length} completed (${i.length} tool${i.length===1?"":"s"}, ${m}ms)`:`Assistant ${s+1}/${e.length} failed after ${m}ms`}),await r("assistant_end",{assistantId:t.assistantId,assistantName:t.name,success:o,durationMs:m,toolsUsed:i,output:typeof l=="string"?l.slice(0,1500):""}),s<e.length-1){const n=p.filter(a=>a.success&&a.output).map(a=>w.replace("{assistantName}",a.assistantName).replace("{content}",String(a.output).substring(0,2e3))).join(`
2
+
3
+ `);n&&(y={messages:[new x({content:[{type:"text",text:`${h}${n}
4
+
5
+ ---
6
+
7
+ ${c}`}]})],namespaceMap:f},await r("team_event",{node:"team_pipeline",kind:"pipeline_context_built",nextAssistantIndex:s+1,totalAssistants:e.length,contextChars:n.length,fromAssistants:p.filter(a=>a.success).map(a=>a.assistantName)}))}}return p}export{C as runPipelineAssistants};
@@ -0,0 +1 @@
1
+ function d(t,s,e){const n=s?.assistantIds,r=e.selectedAssistantIds,u=n&&n.length>0?n:r&&r.length>0?r:null,o=n&&n.length>0?"node-config":r&&r.length>0?"router":null;return{teamAssistants:t&&u?t.filter(i=>u.includes(i.assistantId)):t,effectiveIds:u,filterSource:o}}function c(t,s=""){for(let e=t.length-1;e>=0;e--){const n=t[e];if(n?._getType?.()==="human"||n?.constructor?.name==="HumanMessage")return typeof n?.content=="string"?n.content:n?.content?.[0]?.text??s}return s}function l(t,s){const e=t.length===0?0:Math.max(...t.map(n=>n.turnIndex??0))+1;return s.map(n=>({...n,turnIndex:e}))}export{c as findLatestHumanMessageText,d as resolveTeamAssistants,l as stampResultsWithTurnIndex};
@@ -0,0 +1,13 @@
1
+ import{SystemMessage as D,HumanMessage as A,AIMessage as E}from"@langchain/core/messages";import{DynamicStructuredTool as F}from"@langchain/core/tools";import{dispatchCustomEvent as v}from"@langchain/core/callbacks/dispatch";import{z as c}from"zod";import{createLLMInstance as q}from"../../../llm/providers";import{getNodeInstructions as N}from"../../utils/message-utils";const x="You are a dispatcher deciding WHICH of the candidate teams should handle the user's question.\n\nGiven the user's question and a short list of candidate teams (each with a name and description), pick the ONE team whose description best matches what the question is asking for. You MUST call the tool `select_team` with your decision. Do not produce any other output.",H="I couldn't find a team that handles this \u2014 try rephrasing or contact an admin.";async function O(i,h){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TEAM-FINDER]: "+JSON.stringify(i));const{llmConfig:p,graphDef:y,deps:d,nodeDef:t,searchTeams:T}=h,_=typeof t?.topK=="number"?t.topK:5,m=typeof t?.minScore=="number"?t.minScore:void 0,w=typeof t?.fallbackMessage=="string"&&t.fallbackMessage.trim()?t.fallbackMessage:H,s=[...i.messages||[]].reverse().find(e=>e._getType?.()==="human"||e.constructor?.name==="HumanMessage"),r=typeof s?.content=="string"?s.content:Array.isArray(s?.content)?s.content.map(e=>typeof e=="string"?e:e.text??"").join(""):"",a=()=>({messages:[new E({content:w,additional_kwargs:{__raw_output__:!0}})]});if(!r)return a();const l=await T({owner:d.username||"",query:r,k:_,excludeTeamId:d.teamId}),f=new Set((i.ancestorTeamIds??[]).filter(Boolean)),n=f.size>0?l.filter(e=>!f.has(e.id)):l;if(n.length===0||m!==void 0&&(n[0]?.score??0)<m)return a();if(n.length===1)return{selectedTeamId:n[0].id};const b=n.map((e,u)=>`${u+1}. id="${e.id}" \u2014 ${e.name}
2
+ ${e.description||"(no description)"}`).join(`
3
+
4
+ `),I=new Set(n.map(e=>e.id)),M=new F({name:"select_team",description:"Return the id of the single best-matching team for the user's question.",schema:c.object({teamId:c.string().describe("The id of the chosen team. MUST be one of the candidate ids."),rationale:c.string().describe("One-sentence justification.")}),func:async()=>"ok"}),L=await N(y,t?.id??"team_finder",x),S=new D(L),k=new A(`Candidate teams:
5
+
6
+ ${b}
7
+
8
+ ---
9
+
10
+ User question:
11
+ ${r}
12
+
13
+ Call select_team with the best match.`);try{const e=q(p);if(!e?.bindTools)return console.warn("[team_finder] LLM does not support bindTools \u2014 falling back"),a();const g=(await e.bindTools([M],{tool_choice:{type:"tool",name:"select_team"}}).invoke([S,k]))?.tool_calls?.find(C=>C.name==="select_team"),o=g?.args?.teamId;return o&&I.has(o)?(await v("team_event",{node:"team_finder",kind:"finder_decision",selectedTeamId:o,candidateCount:n.length,rationale:String(g.args.rationale||"").slice(0,500)}),{selectedTeamId:o}):(console.warn("[team_finder] LLM did not return a valid candidate id \u2014 falling back"),a())}catch(e){return console.error("[team_finder] LLM call failed:",e?.message??e),a()}}export{O as execute};
@@ -0,0 +1,3 @@
1
+ import{AIMessage as F,HumanMessage as K,SystemMessage as L}from"@langchain/core/messages";import{dispatchCustomEvent as u}from"@langchain/core/callbacks/dispatch";import{extractAssistantOutput as V}from"../../utils/message-utils";async function Q(a,r){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TEAM-INVOKER]: "+JSON.stringify(a));const{targetTeamId:t,resolveTargetTeam:M,buildAssistantApp:E,deps:p,nodeDef:R,cfg:N}=r,f=N?.signal,i=R?.id??"team_invoker",I=p.teamId,d=e=>(console.warn(`[team_invoker:${i}] ${e}`),{messages:[new F({content:`Error: ${e}`,additional_kwargs:{__raw_output__:!0}})],teamAssistantResults:[{assistantId:"",assistantName:`team_invoker \u2192 ${t??"?"}`,output:`Error: ${e}`,toolsUsed:[],success:!1,durationMs:0}],teamAssistantResultsHistory:a.teamAssistantResultsHistory??[]});if(!t)return d("No targetTeamId configured on the team_invoker node.");const x=Array.isArray(a.ancestorTeamIds)?a.ancestorTeamIds:[],m=Array.from(new Set([...x,I].filter(Boolean)));if(m.includes(t))return d(`Refusing invocation loop: target team (${t}) is already in the invocation chain [${m.join(" -> ")}].`);const _=8;if(m.length>=_)return d(`Refusing invocation: max team invocation depth (${_}) reached [${m.join(" -> ")}].`);const y=await M(t,p.username),n=y?.assistants??[];if(n.length===0)return d(`Target team ${t} resolved to zero runnable assistants.`);const A=a.messages.find(e=>e._getType?.()==="human"||e.constructor?.name==="HumanMessage"),P=typeof A?.content=="string"?A.content:A?.content?.[0]?.text??"",H=["[team_invoker] This run was launched by another team via a team_invoker node.",I?`Source team id: ${I}`:null,r.sourceGraphId?`Source graph id: ${r.sourceGraphId}`:null,r.sourceAssistantId?`Source assistant id: ${r.sourceAssistantId}`:null,`You are part of team "${y?.name??t}" (id: ${t}), invoked to help answer the question below.`].filter(Boolean),D=new L({content:H.join(`
2
+ `)}),U=()=>({messages:[D,new K({content:[{type:"text",text:P}]})],namespaceMap:a.namespaceMap,ancestorTeamIds:[...m,t]});await u("team_event",{node:"team_invoker",kind:"invoke_start",targetTeamId:t,targetTeamName:y?.name,assistantCount:n.length,assistantNames:n.map(e=>e.name)}),await Promise.all(n.map((e,l)=>u("assistant_start",{assistantId:e.assistantId,assistantName:e.name,index:l,total:n.length})));const v=18e4,c=(await Promise.allSettled(n.map(async(e,l)=>{const O=`${p.threadId}-inv-${i}-${l}`,w=Date.now();try{const g=(await E(e,l)).invoke(U(),{configurable:{thread_id:O,checkpoint_ns:""},recursionLimit:100,signal:f}),o=new Promise((z,B)=>setTimeout(()=>B(new Error(`Assistant timeout after ${v}ms`)),v)),$=await Promise.race([g,o]),j=$?.messages||[],T=V(j),S=$?.toolsUsedAccum||[],b=Date.now()-w;return await u("assistant_end",{assistantId:e.assistantId,assistantName:e.name,success:!0,durationMs:b,toolsUsed:S,output:typeof T=="string"?T.slice(0,1500):""}),{assistantId:e.assistantId,assistantName:e.name,output:T,toolsUsed:S,success:!0,durationMs:b}}catch(s){const g=Date.now()-w,o=s?.name==="AbortError"||f?.aborted===!0||/aborted/i.test(String(s?.message??""));return o?console.log(`[team_invoker:${i}] \u{1F6D1} Assistant ${e.name} cancelled by user`):(console.error(`[team_invoker:${i}] Assistant ${e.name} failed:`,s.message),s?.stack&&console.error(`[team_invoker:${i}] Stack:
3
+ ${s.stack}`)),await u("assistant_end",{assistantId:e.assistantId,assistantName:e.name,success:!1,durationMs:g,toolsUsed:[],errorStack:o?void 0:s?.stack}),{assistantId:e.assistantId,assistantName:e.name,output:o?"Cancelled by user":`Error: ${s.message}`,toolsUsed:[],success:!1,durationMs:g,errorStack:o?void 0:s?.stack}}}))).map(e=>e.status==="fulfilled"?e.value:{assistantId:"",assistantName:"unknown",output:"",toolsUsed:[],success:!1,durationMs:0}),h=c.filter(e=>e.success).length;await u("team_event",{node:"team_invoker",kind:"invoke_end",targetTeamId:t,assistantCount:c.length,successCount:h,failedCount:c.length-h,aborted:f?.aborted??!1});const k=a.teamAssistantResultsHistory??[],C=k.length===0?0:Math.max(...k.map(e=>e.turnIndex??0))+1,G=c.map(e=>({...e,turnIndex:C}));return{messages:[],teamAssistantResults:c,teamAssistantResultsHistory:G}}export{Q as execute};
@@ -0,0 +1 @@
1
+ import{HumanMessage as U}from"@langchain/core/messages";import{dispatchCustomEvent as i}from"@langchain/core/callbacks/dispatch";import{extractAssistantOutput as O}from"../../utils/message-utils";async function B(n,S){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TEAM-PARALLEL]: "+JSON.stringify(n));const{teamAssistants:m,buildAssistantApp:$,deps:E,nodeDef:v,cfg:M}=S,d=M?.signal,a=v?.assistantIds,o=n.selectedAssistantIds,u=a&&a.length>0?a:o&&o.length>0?o:null,p=a&&a.length>0?"node-config":o&&o.length>0?"router":null,t=u?m.filter(s=>u.includes(s.assistantId)):m;p&&(console.log(`[team_parallel] ${p} filter: ${t.length}/${m.length} assistants will run (configured: [${u.join(", ")}], resolved: [${t.map(s=>s.name).join(", ")}])`),t.length===0&&console.warn(`[team_parallel] \u26A0\uFE0F ${p} filter resolved to ZERO assistants \u2014 none of the configured IDs are in the team's assistant list. Parallel block will produce no results.`));const g=n.messages.find(s=>s._getType?.()==="human"||s.constructor?.name==="HumanMessage"),D=typeof g?.content=="string"?g.content:g?.content?.[0]?.text??"",P={messages:[new U({content:[{type:"text",text:D}]})],namespaceMap:n.namespaceMap};await i("team_event",{node:"team_parallel",kind:"parallel_start",assistantCount:t.length,assistantNames:t.map(s=>s.name)});const A=18e4,N=async(s,f)=>{const _=`${E.threadId}-ta-${f}`,w=Date.now();await i("assistant_start",{assistantId:s.assistantId,assistantName:s.name,index:f,total:t.length,subThreadId:_});try{const l=(await $(s,f)).invoke(P,{configurable:{thread_id:_,checkpoint_ns:""},recursionLimit:100,signal:d}),c=new Promise((L,C)=>setTimeout(()=>C(new Error(`Assistant timeout after ${A}ms`)),A)),T=await Promise.race([l,c]),k=T?.messages||[],y=O(k),b=T?.toolsUsedAccum||[],x=Date.now()-w;return await i("assistant_end",{assistantId:s.assistantId,assistantName:s.name,success:!0,durationMs:x,toolsUsed:b,output:typeof y=="string"?y.slice(0,1500):""}),{assistantId:s.assistantId,assistantName:s.name,output:y,toolsUsed:b,success:!0,durationMs:x}}catch(r){const l=Date.now()-w,c=r?.name==="AbortError"||d?.aborted===!0||/aborted/i.test(String(r?.message??""));return c?console.log(`[team_parallel] \u{1F6D1} Assistant ${s.name} cancelled by user`):console.error(`[team_parallel] Assistant ${s.name} failed:`,r.message),await i("assistant_end",{assistantId:s.assistantId,assistantName:s.name,success:!1,durationMs:l,toolsUsed:[]}),{assistantId:s.assistantId,assistantName:s.name,output:c?"Cancelled by user":`Error: ${r.message}`,toolsUsed:[],success:!1,durationMs:l}}},e=[];for(let s=0;s<t.length;s++)e.push(await N(t[s],s));const h=e.filter(s=>s.success).length;await i("team_event",{node:"team_parallel",kind:"parallel_end",assistantCount:e.length,successCount:h,failedCount:e.length-h,aborted:d?.aborted??!1});const I=n.teamAssistantResultsHistory??[],R=I.length===0?0:Math.max(...I.map(s=>s.turnIndex??0))+1,H=e.map(s=>({...s,turnIndex:R}));return{messages:[],teamAssistantResults:e,teamAssistantResultsHistory:H}}export{B as execute};
@@ -0,0 +1,6 @@
1
+ import{dispatchCustomEvent as d}from"@langchain/core/callbacks/dispatch";import{extractCrossTurnHistory as P}from"../../utils/message-utils";import{resolveTeamAssistants as _,findLatestHumanMessageText as x,stampResultsWithTurnIndex as v}from"./team-execution/team-assistant-utils";import{runPipelineAssistants as w}from"./team-execution/pipeline-runner";import{autoSaveTeamPipelineMemory as S}from"./team-execution/pipeline-memory";const b=`[Previous analysis \u2014 {assistantName}]
2
+ {content}`;async function I(s,f){const{teamAssistants:a,buildAssistantApp:g,deps:m,nodeDef:r,cfg:y}=f;process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TEAM-PIPELINE]: "+JSON.stringify(s));const p=y?.signal,{teamAssistants:e=[],effectiveIds:l,filterSource:i}=_(a,r,s);i&&(console.log(`[team_pipeline] ${i} filter: ${e.length}/${a.length} assistants will run (configured: [${l.join(", ")}], resolved: [${e.map(n=>n.name).join(", ")}])`),e.length===0&&console.warn(`[team_pipeline] \u26A0\uFE0F ${i} filter resolved to ZERO assistants \u2014 none of the configured IDs are in the team's assistant list. Pipeline will produce no results.`));const T=r?.instructions||b,c=x(s.messages),o=P(s.messages,{maxTurns:3}),A=o?`${o}
3
+
4
+ ---
5
+
6
+ `:"";await d("team_event",{node:"team_pipeline",kind:"pipeline_start",assistantCount:e.length,assistantNames:e.map(n=>n.name),routedSubset:!!l&&l.length>0&&e.length<a.length,filterSource:i,candidatePoolSize:a.length,priorTurnsInjected:o?o.length:0});const t=await w({teamAssistants:e,buildAssistantApp:g,deps:m,abortSignal:p,contextTemplate:T,historyPrefix:A,originalText:c,namespaceMap:s.namespaceMap,topic:s.topic});await S({results:t,deps:m,nodeDef:r,originalText:c});const u=t.filter(n=>n.success).length,h=t.length-u;await d("team_event",{node:"team_pipeline",kind:"pipeline_end",assistantCount:t.length,successCount:u,failedCount:h,aborted:p?.aborted??!1});const E=v(s.teamAssistantResultsHistory??[],t);return{messages:[],teamAssistantResults:t,teamAssistantResultsHistory:E}}export{I as execute};
@@ -0,0 +1,26 @@
1
+ import{SystemMessage as S,HumanMessage as v}from"@langchain/core/messages";import{DynamicStructuredTool as N}from"@langchain/core/tools";import{dispatchCustomEvent as R}from"@langchain/core/callbacks/dispatch";import{z as l}from"zod";import{createLLMInstance as O}from"../../../llm/providers";import{getNodeInstructions as C}from"../../utils/message-utils";import{logNodeExecution as $}from"../../utils/logging-utils";const k=`You are a routing dispatcher for a team of specialist AI assistants.
2
+
3
+ Given the user's question and a list of available assistants (each with a name, description, and topic), decide WHICH assistants are actually needed to answer.
4
+
5
+ Principles:
6
+ 1. Pick the SMALLEST useful subset. Do NOT include assistants whose tools are irrelevant.
7
+ 2. Match the question against each assistant's DESCRIPTION/ROLE (the text under its name), not just its name or topic. The role tells you what the assistant is actually for.
8
+ 3. ONLY-memory applies to a trivial recall of a previously-stored fact ("what is X's name?", "remind me of Y"). A question that ANALYSES or EVALUATES a domain ("which candidate is best for role Z?", "analyse the storage of cluster C") needs that DOMAIN specialist \u2014 pick it (optionally alongside the memory assistant), never the memory assistant alone.
9
+ 4. Do NOT pick the memory assistant alone on the assumption that "the answer is probably already stored" or "was analysed before". The memory assistant only retrieves past notes; it CANNOT run the domain's live tools. If the question concerns a domain (recruitment, email, documents, a cluster, \u2026), you MUST include that domain's specialist so the answer is produced from fresh data \u2014 even if a prior answer might exist in memory.
10
+ 5. New search/action questions ("find X", "send Y", "create Z") need the corresponding domain specialist(s).
11
+ 6. When in doubt whether two assistants are both useful, include the one whose description matches the question best.
12
+ 7. NEVER pick zero assistants \u2014 always select at least one.
13
+
14
+ You MUST call the tool \`select_assistants\` with your decision. Do not produce any other output.`;async function W(c,y){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TEAM-ROUTER]: "+JSON.stringify(c));const{llmConfig:d,graphDef:g,teamAssistants:e,nodeDef:w}=y,m=Date.now();if($("TEAM_ROUTER",d,{candidates:e?.length??0}),!e||e.length===0)return{};if(e.length===1)return{selectedAssistantIds:[e[0].assistantId],teamRouterDecision:{candidates:e.map(t=>({assistantId:t.assistantId,name:t.name})),selected:[e[0].assistantId],rationale:"Only one candidate available \u2014 no routing needed",durationMs:Date.now()-m}};const o=[...c.messages||[]].reverse().find(t=>t._getType?.()==="human"||t.constructor?.name==="HumanMessage"),T=typeof o?.content=="string"?o.content:Array.isArray(o?.content)?o.content.map(t=>typeof t=="string"?t:t.text??"").join(""):"",I=t=>{const r=t.description||t.summary||t.context?.role||t.role||t.metadata?.description||"";return String(r).trim()||"(no description)"},A=e.map((t,r)=>{const p=t.name||t.assistantId,n=I(t),a=t.topic?` [topic: ${t.topic}]`:"";return`${r+1}. id="${t.assistantId}" \u2014 ${p}${a}
15
+ ${n}`}).join(`
16
+
17
+ `),b=new Set(e.map(t=>t.assistantId)),D=new N({name:"select_assistants",description:"Return the minimal subset of assistant IDs needed to answer the user's question, with a brief rationale.",schema:l.object({assistantIds:l.array(l.string()).min(1).describe("Array of assistant IDs to run. MUST contain at least one ID from the candidate list."),rationale:l.string().describe("One-sentence justification explaining why these assistants suffice.")}),func:async()=>"ok"}),M=await C(g,w?.id??"team_router",k),_=new S(M),L=new v(`Available assistants:
18
+
19
+ ${A}
20
+
21
+ ---
22
+
23
+ User question:
24
+ ${T}
25
+
26
+ Call select_assistants with the IDs needed.`);let s,i="";try{const t=O(d);if(!t?.bindTools)return console.warn("[team_router] LLM does not support bindTools \u2014 falling back to all assistants"),{};const n=(await t.bindTools([D],{tool_choice:{type:"tool",name:"select_assistants"}}).invoke([_,L]))?.tool_calls?.find(a=>a.name==="select_assistants");if(n?.args){const a=Array.isArray(n.args.assistantIds)?n.args.assistantIds:[],f=a.filter(E=>b.has(E));f.length>0?(s=f,i=String(n.args.rationale||"").slice(0,500)):console.warn(`[team_router] LLM returned ${a.length} ids but none matched candidates \u2014 falling back to all`)}else console.warn("[team_router] LLM did not call select_assistants \u2014 falling back to all assistants")}catch(t){return console.error("[team_router] LLM call failed:",t?.message??t),{}}const u=Date.now()-m;if(!s||s.length===0)return{};const h=e.filter(t=>s.includes(t.assistantId)).map(t=>t.name);return console.log(`[team_router] \u{1F9ED} Selected ${s.length}/${e.length} assistants: [${h.join(", ")}] \u2014 ${i}`),await R("team_event",{node:"team_router",kind:"router_decision",selectedCount:s.length,candidateCount:e.length,selectedNames:h,rationale:i,durationMs:u}),{selectedAssistantIds:s,teamRouterDecision:{candidates:e.map(t=>({assistantId:t.assistantId,name:t.name})),selected:s,rationale:i,durationMs:u}}}export{W as execute};
@@ -0,0 +1,6 @@
1
+ import{AIMessage as g,HumanMessage as J}from"@langchain/core/messages";import{interrupt as P}from"@langchain/langgraph";import{createLLMInstance as X}from"../../../../llm/providers";import{getNodeInstructions as H,filterSystemMessages as z,filterNonSystemMessages as G}from"../../../utils/message-utils";import{interpolateEngineVars as V}from"../../../utils/engine-vars";import{lastAIMessageContent as Y,lastHumanMessageContent as q}from"../../../utils/tool-result";import{runInSandbox as K}from"./sandbox";import{buildToolBridge as Q,sanitizeIdentifier as _}from"./tool-bridge";import{describeToolParams as W}from"../../../utils/schema-utils";import{fetchResources as Z,buildResourcesData as ee,formatResourcesSummary as se}from"./resource-bridge";const oe=6e4,te=128;function ne(e){const s=new Map;for(const o of e){const c=_(o._system||o._mcpServerName||"tools"),n=_(o.name);s.has(c)||s.set(c,[]),s.get(c).push({method:n,params:W(o),description:o.description})}return[...s.entries()].map(([o,c])=>`${o}:
2
+ `+c.map(n=>` ${n.method}(${n.params?`{${n.params}}`:""})${n.description?` \u2014 ${n.description}`:""}`).join(`
3
+ `)).join(`
4
+ `)}function re(e){const s=/```(?:js|javascript|ts|typescript)?\n([\s\S]*?)```/.exec(e);return s?s[1]:null}async function Ee(e,s){const{llmConfig:o,graphDef:c,tools:n,cfg:R,assistant:f,channel:I,username:y}=s,N=s.timeoutMs??oe,w=s.maxMemoryMb??te,x=(f?.resources_policy?.resources||[]).map(r=>r?.id).filter(Boolean),E=x.length>0||y?await Z(y??"",x):[],C=e?.customFields??{},$=ee(E,C);let a=(await H(c,s.nodeDef?.id??"code_executor",void 0,f)).replace(/\{\{availableTools\}\}/g,ne(n));a=a.replace(/\{\{availableResources\}\}/g,se(E));const v=Y(e?.messages??[]),O=q(e?.messages??[]);a=V(a,e,{channel:I,previousNodeOutput:v,lastUserMessage:O});const M=z(e.messages??[]),S=M[M.length-1]?.content||"",D=S?`${S}
5
+
6
+ ${a}`:a,T=`${o.provider}:${o.model}`,i=G(e.messages??[]),h=i[i.length-1]?.getType(),A=h==="tool"||h==="ai"?[...i,new J("Continue: write the JS script now based on the context above.")]:i,F=X(o);let m;try{m=await F.invoke([{role:"system",content:D},...A])}catch(r){throw new Error(`[code_executor llm=${T}] ${r.message}`,{cause:r})}const p=typeof m.content=="string"?m.content:JSON.stringify(m.content),l=re(p);if(!l)return console.warn(`[code_executor llm=${T}] No fenced code block found. Raw LLM content (first 2000 chars): ${p.slice(0,2e3)}`),{messages:[new g(JSON.stringify({error:"TOOL_EXECUTION_FAILED",error_message:"No fenced code block found in code_executor LLM response"}))],toolExecRounds:e?.toolExecRounds??0,codeExecScript:p};const B=e?.codeExecTrace??[],{hostFunctions:U,getTrace:k}=Q({tools:n,cfg:R,namespaceMap:e?.namespaceMap??{},replayedTrace:B,onDestructiveCall:async({jsPath:r,toolName:L,args:b})=>P({type:"approval",message:`Autoriser l'appel destructif "${L}" ?`,details:JSON.stringify(b),payload:{jsPath:r,toolName:L,args:b}})}),t=await K({scriptBody:l,hostFunctions:U,timeoutMs:N,maxMemoryMb:w,extraGlobals:{resources:$}}),u=k(),j=u.map(r=>r.jsPath.split(".").slice(1).join(".")),d=e?.toolExecRounds??0;return t.ok?{messages:[new g(typeof t.value=="string"?t.value:JSON.stringify(t.value))],toolsUsedAccum:j,toolExecRounds:d+1,codeExecTrace:u,codeExecScript:l,codeExecConsoleLogs:t.consoleLogs,codeExecStats:t.stats}:{messages:[new g(JSON.stringify({error:"TOOL_EXECUTION_FAILED",error_kind:t.error?.kind,error_message:t.error?.message}))],toolExecRounds:t.error?.kind==="syntax"?d:d+1,codeExecTrace:u,codeExecScript:l,codeExecConsoleLogs:t.consoleLogs,codeExecStats:t.stats}}export{Ee as execute,ne as groupToolsByNamespace};
@@ -0,0 +1,2 @@
1
+ import{Client as a}from"@elastic/elasticsearch";import{sanitizeIdentifier as i}from"./tool-bridge";const c=new a({node:process.env.ELASTICSEARCH_HOST||"https://51.159.174.230:9205",auth:{username:process.env.ELASTICSEARCH_USER||"elastic",password:process.env.ELASTICSEARCH_PASSWORD||"diagnostics"},tls:{rejectUnauthorized:!1}});async function d(n,t){if(t&&t.length>0)try{return((await c.mget({index:".stkxp_resources",body:{ids:t}})).docs||[]).filter(e=>e.found).map(e=>e._source).filter(e=>e?.title)}catch{return[]}if(!n)return[];try{return(await c.search({index:".stkxp_resources",body:{query:{bool:{should:[{term:{owner:n}},{term:{owner:"stkxp"}}],minimum_should_match:1}},size:100,_source:{excludes:["semantic_content"]}}})).hits.hits.map(e=>e._source).filter(e=>e?.title)}catch{return[]}}function p(n,t,r){if(!n||!t||t.length===0)return n;let e=n;for(const s of t){if(r[s]===void 0)continue;const o=r[s],u=typeof o=="string"?o:JSON.stringify(o);e=e.split(`{{${s}}}`).join(u)}return e}function g(n,t){const r={};for(const e of n){const s=i(e.title);r[s]={...e,prompt_text:p(e.prompt_text??"",e.variables,t)}}return r}function m(n){return n.length===0?"(none)":n.map(t=>{const r=i(t.title),e=[t.description,t.use_case?`use_case: ${t.use_case}`:"",t.type?`type: ${t.type}`:""].filter(Boolean).join(" \u2014 ");return`- ${r} ("${t.title}")${e?`: ${e}`:""}`}).join(`
2
+ `)}export{g as buildResourcesData,d as fetchResources,m as formatResourcesSummary,p as interpolateResourceVars};
@@ -0,0 +1,6 @@
1
+ import p from"isolated-vm";async function f(e){try{const s=await e.getHeapStatistics();return{wallTimeMs:Number(e.wallTime)/1e6,cpuTimeMs:Number(e.cpuTime)/1e6,heapUsedMb:s.used_heap_size/(1024*1024)}}catch{return}}function b(e){const s=e.split("."),o=/^[A-Za-z_$][A-Za-z0-9_$]*$/;for(const a of s)if(!o.test(a))throw new Error(`Invalid host function jsPath segment "${a}" in "${e}"`)}function w(e){const s=["const tools = {};"];return e.forEach((o,a)=>{b(o.jsPath);const l=o.jsPath.split(".");let i="tools";for(let n=0;n<l.length-1;n++)i+=`.${l[n]}`,s.push(`${i} = ${i} || {};`);const u=`tools.${o.jsPath}`;s.push(`${u} = function(args) {`,` return __hostRef_${a}.apply(undefined, [JSON.stringify(args)], { arguments: { copy: true }, result: { promise: true, copy: true } })`," .then((json) => json === undefined ? undefined : JSON.parse(json));","};")}),s.join(`
2
+ `)}async function $(e){const{scriptBody:s,hostFunctions:o,timeoutMs:a,maxMemoryMb:l,extraGlobals:i}=e,u=[];let n;try{n=new p.Isolate({memoryLimit:l});const g=await n.createContext(),c=g.global;await c.set("global",c.derefInto());const y=new p.Reference((...t)=>{u.push(t.map(r=>typeof r=="string"?r:JSON.stringify(r)).join(" "))});await c.set("__consoleLog",y);for(let t=0;t<o.length;t++){const r=o[t],m=new p.Reference(async S=>await r.call(S));await c.set(`__hostRef_${t}`,m)}if(i)for(const[t,r]of Object.entries(i))await c.set(t,r,{copy:!0});const h=`${["const console = { log: (...args) => __hostLogWrapper(...args) };",'function __hostLogWrapper(...args) { __consoleLog.applySync(undefined, args.map(a => typeof a === "string" ? a : JSON.stringify(a)), { arguments: { copy: true } }); }',w(o)].join(`
3
+ `)}
4
+ (async () => {
5
+ ${s}
6
+ })()`;let d;try{d=await n.compileScript(h)}catch(t){return{ok:!1,consoleLogs:u,error:{kind:"syntax",message:t.message}}}try{return{ok:!0,value:await d.run(g,{timeout:a,promise:!0,copy:!0}),consoleLogs:u,stats:await f(n)}}catch(t){const r=/timed? ?out/i.test(t.message??""),m=/isolate.*disposed|memory/i.test(t.message??"");return{ok:!1,consoleLogs:u,error:{kind:r?"timeout":m?"memory":"runtime",message:t.message??String(t)},stats:await f(n)}}}finally{n?.dispose()}}export{$ as runInSandbox};
@@ -0,0 +1 @@
1
+ import{invokeWithTimeout as P}from"../../tools/tool-execution/invoke";import{applyNamespaceGuard as x}from"../../tools/tool-execution/namespace-guard";import{coerceToJson as E}from"../../../utils/tool-result";function S(n){if(typeof n!="string")return n;const t=E(n);return Array.isArray(t)||t!==null&&typeof t=="object"?t:n}function p(n){return n.replace(/[^A-Za-z0-9_$]/g,"_").replace(/^[0-9]/,"_$&")}function I(n){const{tools:t,cfg:g,namespaceMap:f,replayedTrace:d,onDestructiveCall:y}=n,a=[];let h=0;return{hostFunctions:t.map(e=>{const T=p(e._system||e._mcpServerName||"tools"),w=p(e.name),o=`${T}.${w}`;return{jsPath:o,call:async u=>{const i=u===void 0?{}:JSON.parse(u),l=h++,s=d.find(r=>r.callId===l&&r.jsPath===o);if(s){if(a.push(s),s.error)throw new Error(s.error);return JSON.stringify(s.result??null)}if(e._destructiveHint===!0){const r=await y({jsPath:o,toolName:e.name,args:i});if(!r.approved){const c={callId:l,jsPath:o,args:i,result:{error:"APPROVAL_REJECTED",comment:r.comment}};return a.push(c),JSON.stringify(c.result)}}try{const r=[{name:e.name,args:i}];x({toolCalls:r,finalTools:t,namespaceMap:f,messages:[]});const c=r[0].args,m=S(await P(e,c,g,e.name));return a.push({callId:l,jsPath:o,args:c,result:m}),JSON.stringify(m??null)}catch(r){throw a.push({callId:l,jsPath:o,args:i,error:r.message??String(r)}),r}}}}),getTrace:()=>a}}export{I as buildToolBridge,p as sanitizeIdentifier};
@@ -0,0 +1,5 @@
1
+ import{SystemMessage as _,ToolMessage as p}from"@langchain/core/messages";import{createLLMInstance as L}from"../../../llm/providers";async function N(r,f){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][LOCAL-EXTRACTOR]: "+JSON.stringify(r));const{llmConfig:l,extractorInstructions:i}=f,s=r.messages.filter(e=>e._getType()==="tool");if(s.length===0)return console.log("[local_extractor] No ToolMessages found \u2014 pass-through"),{};console.log(`[local_extractor] Processing ${s.length} ToolMessage(s)`);const n={...r.entityTokenMap};let y=Object.keys(n).length;const m=[{regex:/\b(?:\d{1,3}\.){3}\d{1,3}\b/g,prefix:"ip"},{regex:/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-z]{2,}/g,prefix:"email"},{regex:/\b[a-z0-9][-a-z0-9.]*\.[a-z]{2,4}\b/gi,prefix:"host"}];function x(e){let t=e;for(const{regex:a,prefix:c}of m)t=t.replace(a,o=>(n[o]||(n[o]=`${c}_${++y}`),n[o]));return t}const g=s.map(e=>{const t=typeof e.content=="string"?e.content:JSON.stringify(e.content);return new p({tool_call_id:e.tool_call_id,content:x(t)})});if(l&&i)try{const{HumanMessage:e}=await import("@langchain/core/messages"),t=L(l),a=new _(i),c=new e(g.map(d=>d.content).join(`
2
+
3
+ ---
4
+
5
+ `)),o=await t.invoke([a,c]),M=typeof o.content=="string"?o.content:JSON.stringify(o.content),T=s[s.length-1].tool_call_id??"extracted",u=new p({tool_call_id:T,content:M});return console.log("[local_extractor] LLM extraction complete \u2014 replacing ToolMessages with summary"),{messages:[u],entityTokenMap:n}}catch(e){console.error("[local_extractor] Local LLM failed \u2014 falling back to pre-anonymised data:",e?.message??e)}return{messages:g,entityTokenMap:n}}export{N as execute};
@@ -0,0 +1,47 @@
1
+ import{SystemMessage as D,AIMessage as B}from"@langchain/core/messages";import{createLLMInstance as Y}from"../../../llm/providers";import{filterSystemMessages as J,filterNonSystemMessages as H,deduplicateToolMessages as G,getNodeInstructions as F,sanitizeToolMessages as U}from"../../utils/message-utils";import{logNodeExecution as K}from"../../utils/logging-utils";import{interpolateEngineVars as V}from"../../utils/engine-vars";const z=["markdown","table","echarts","recharts","eui","mermaid","leaflet","remotion","mantine"],W={slack:`\u26A0\uFE0F CHANNEL CONSTRAINT (channel="slack") \u2014 THIS OVERRIDES EVERYTHING ABOVE: if any instruction above (including your own persona/task instructions) shows example JSON snippets, chart formats, markdown documents, code fences, or a "recommended report structure" \u2014 those are illustrative/informational ONLY, possibly written for a different rendering pipeline. They do NOT define your actual output contract. Your literal, final output for THIS response must follow ONLY the rules below, with no exceptions and no blending of formats.
2
+
3
+ This response is rendered through a live Slack Block Kit streaming pipeline that only understands NATIVE Slack Block Kit block objects \u2014 it does NOT convert stkxp-app's own dashboard block types (markdown/table/echarts/recharts/eui/leaflet/mermaid/mantine/remotion/form as {title,body} or {columns,data} etc.) and will silently drop them, producing an empty Slack message.
4
+
5
+ Your response MUST be NDJSON (one line = one complete, standalone Slack block object). The first character of your response MUST be \`{\`. Do NOT return a JSON array, a {"blocks":[...]} wrapper, markdown code fences, or any prose outside JSON objects.
6
+
7
+ You may output ONLY these top-level block types: header, section, fields, context, divider, actions, image, rich_text, markdown, table, data_table, data_visualization, video, card, carousel, container.
8
+
9
+ Two of these type strings have a DIFFERENT native shape here than stkxp-app's own dashboard blocks \u2014 use ONLY the native shape below:
10
+ - "table": {"type":"table","column_settings":[...],"rows":[[{"type":"raw_text","text":"..."},{"type":"raw_number","value":123}],...]} \u2014 NOT {"columns":[...],"data":[...]}.
11
+ - "markdown": {"type":"markdown","text":"## ...\\n\\n- point 1\\n- point 2"} \u2014 NOT {"title":"...","body":"..."}.
12
+
13
+ Examples of other native blocks:
14
+ {"type":"header","text":{"type":"plain_text","text":"\u{1F4CA} Analysis","emoji":true}}
15
+ {"type":"section","text":{"type":"mrkdwn","text":"*Key finding*\\nLatency increased from *120ms* to *410ms*."}}
16
+ {"type":"fields","items":[{"title":"Status","value":"Degraded"},{"title":"Env","value":"Production"}]}
17
+ {"type":"context","elements":[{"type":"mrkdwn","text":"Window: 24h \u2022 Updated: 12 Aug 2026 08:30 UTC"}]}
18
+ {"type":"data_visualization","chart_type":"bar","title":{"type":"plain_text","text":"Errors by service"},"categories":["API","Search"],"series":[{"name":"Errors","values":[128,84]}]}
19
+
20
+ Never emit: echarts, recharts, eui, leaflet, mermaid, mantine, remotion, form, or any other stkxp-app-only dashboard block type \u2014 none of them render on this channel.
21
+
22
+ FINAL CHECK before you answer: your entire response is a sequence of lines, each line exactly one JSON object matching the native shapes above. No prose, no headers, no "\`\`\`json" fences, no narrative document, no chart shape other than the one shown above. If you find yourself writing a paragraph, a "###" heading, or a fenced code block, stop and convert it into the matching native block type instead.`};async function ne(a,x){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][RESPONSE-GENERATOR]: "+JSON.stringify(a));const{llmConfig:y,graphDef:O,cfg:u,assistant:h,channel:l}=x;console.log(`[assistant_response_generator] channel=${l??"web"}`);const i=J(a.messages);let t=H(a.messages);t=G(t),t=U(t);const v=await F(O,"assistant_response_generator",void 0,h),E=V(v,a,{channel:l}),f=i.length>0?typeof i[0].content=="string"?i[0].content:String(i[0].content):"You are a response generator. Generate a comprehensive dashboard with multiple blocks.",C=a.userContext&&!f.includes(a.userContext)?`
23
+
24
+ User Context:
25
+ ${a.userContext}`:"",b=t.filter(e=>e.getType()==="ai"&&Array.isArray(e.tool_calls)&&e.tool_calls.length>0).flatMap(e=>e.tool_calls).map(e=>`- "${e.id}" \u2192 ${e.name}`).join(`
26
+ `),_=b?`
27
+
28
+ Tool calls executed in this run \u2014 add "_toolCallId": "<id>" to each block that uses tool data:
29
+ ${b}
30
+ If a block uses no tool data, omit _toolCallId.`:"",p=[...i].reverse().find(e=>typeof e.content=="string"&&e.content.startsWith("Compressed tool results:")),M=p&&typeof p.content=="string"?`
31
+
32
+ ${p.content}`:"",c=h?.output_policy?.enabledBlockTypes,N=c&&c.length>0?z.filter(e=>!c.includes(e)):[],$=N.length>0?`
33
+
34
+ Block type restriction for this assistant: you may ONLY use these dashboard block types: ${c.join(", ")}. Never emit any of these disabled block types, even if your instructions above show examples using them: ${N.join(", ")}.`:"",S=l?W[l]:void 0,I=S?`
35
+
36
+ ${S}`:"",k=`${E}${f}${C}${_}${M}${$}${I}`;K("RESPONSE GENERATOR",y,{totalMessages:t.length});const R=t.reduce((e,r)=>{const o=r.getType();return e[o]=(e[o]||0)+1,e},{});console.log("\u{1F4CA} Message breakdown:",R),console.log("\u{1F4DD} All messages:"),t.forEach((e,r)=>{const o=e.getType(),m=typeof e.content=="string"?e.content.substring(0,100):JSON.stringify(e.content).substring(0,100);console.log(` ${r+1}. ${o}: ${m}...`)});let T=[...t];const d=t[t.length-1]?.getType();if(d==="tool"||d==="ai"){console.log(`\u{1F527} Detected conversation ending with ${d==="tool"?"ToolMessage":"AIMessage (e.g. from upstream subgraph)"} - adding continuation prompt`);const{HumanMessage:r}=await import("@langchain/core/messages"),o=t.filter(s=>s.getType()==="ai"&&Array.isArray(s.tool_calls)&&s.tool_calls.length>0).flatMap(s=>s.tool_calls).map(s=>`- "${s.id}" \u2192 ${s.name}`).join(`
37
+ `),m=o?`
38
+
39
+ Tool calls executed (add "_toolCallId" to each block that uses tool data):
40
+ ${o}
41
+ Example: {"type":"table","title":"...","_toolCallId":"<id>","data":[...],"columns":[...]}
42
+ If a block uses no tool data (e.g. a static recommendations block), omit _toolCallId.`:"",j=new r(`\u26A0\uFE0F STOP. Do NOT call any tools. Do NOT write conversational text.
43
+ The tool results above contain all the data you need.
44
+ Your ONLY task RIGHT NOW: output a complete NDJSON response (one JSON object per line) with multiple blocks (markdown, echarts, eui, table) based on the tool results.`+m+`
45
+ Start your response immediately with the first JSON object on line 1. No preamble.`);T.push(j),console.log("\u2705 Added continuation prompt to trigger response generation")}const L=Y(y),w=u?.signal;let g="";const P=await L.stream([new D(k),...T],{configurable:u?.configurable,signal:w});for await(const e of P){if(w?.aborted){console.log(`\u{1F6D1} Response generator aborted after ${g.length} chars`);break}const r=typeof e.content=="string"?e.content:Array.isArray(e.content)?e.content.map(o=>typeof o=="string"?o:o?.text??"").join(""):"";g+=r}const n=new B({content:g});console.log(`
46
+ `+"=".repeat(80)),console.log("\u{1F4E5} RESPONSE GENERATOR - Final response generated"),console.log("=".repeat(80)),console.log(`\u{1F4CB} AIMessage type: ${typeof n.content}`),console.log(`\u{1F4CB} AIMessage is array: ${Array.isArray(n.content)}`);const A=typeof n.content=="string"?n.content.length:0;if(console.log(`\u{1F4DD} Content length: ${A} chars`),A>0){const e=typeof n.content=="string"?n.content.substring(0,200):JSON.stringify(n.content).substring(0,200);console.log(`\u{1F4C4} Content preview: ${e}...`)}else Array.isArray(n.content)?console.log(`\u{1F4C4} Content is array with ${n.content.length} items:`,n.content):console.log("\u26A0\uFE0F Content is empty or unexpected type");return console.log("=".repeat(80)+`
47
+ `),{messages:[n],systemPromptFinal:k}}export{ne as execute};
@@ -0,0 +1 @@
1
+ import{AIMessage as g}from"@langchain/core/messages";import{interrupt as b}from"@langchain/langgraph";import{getNodeInstructions as A}from"../../../utils/message-utils";import{lastAIMessageContent as C,lastHumanMessageContent as D}from"../../../utils/tool-result";import{runInSandbox as v}from"../code-executor/sandbox";import{buildToolBridge as L}from"../code-executor/tool-bridge";import{fetchResources as F,buildResourcesData as O}from"../code-executor/resource-bridge";import{buildAvailableTools as U,buildAvailableResources as k}from"../../../utils/sandbox-catalog";const w=6e4,P=128;async function q(e,s){const{graphDef:y,tools:l,cfg:x,assistant:r}=s,E=s.timeoutMs??w,f=s.maxMemoryMb??P,n=await A(y,s.nodeDef?.id??"static_code_executor",void 0,r),T=e?.codeExecTrace??[],{hostFunctions:M,getTrace:I}=L({tools:l,cfg:x,namespaceMap:e?.namespaceMap??{},replayedTrace:T,onDestructiveCall:async({jsPath:t,toolName:c,args:p})=>b({type:"approval",message:`Autoriser l'appel destructif "${c}" ?`,details:JSON.stringify(p),payload:{jsPath:t,toolName:c,args:p}})}),d={threadId:e?.threadId,assistantId:r?.assistantId??r?.id,topic:e?.topic,userContext:e?.userContext,channel:s.channel,compareChatId:e?.compareChatId,enrichChatId:e?.enrichChatId,last_tool_error:e?.last_tool_error,namespaceMap:e?.namespaceMap??{},teamAssistantResults:e?.teamAssistantResults,teamAssistantResultsHistory:e?.teamAssistantResultsHistory,selectedAssistantIds:e?.selectedAssistantIds,selectedTeamId:e?.selectedTeamId,keywords:e?.keywords,language:e?.language,teamRouterDecision:e?.teamRouterDecision,toolExecRounds:e?.toolExecRounds,toolsUsedAccum:e?.toolsUsedAccum,systemPromptTools:e?.systemPromptTools,systemPromptFinal:e?.systemPromptFinal,codeExecTrace:e?.codeExecTrace,codeExecScript:e?.codeExecScript,compressionStats:e?.compressionStats,entityTokenMap:e?.entityTokenMap,previousNodeOutput:C(e?.messages??[]),lastUserMessage:D(e?.messages??[]),customFields:e?.customFields??{}},m=(r?.resources_policy?.resources||[]).map(t=>t?.id).filter(Boolean),u=m.length>0||s.username?await F(s.username??"",m):[],h=O(u,d.customFields),R=U(l),S=k(u),o=await v({scriptBody:n,hostFunctions:M,timeoutMs:E,maxMemoryMb:f,extraGlobals:{context:d,resources:h,availableTools:R,availableResources:S}}),a=I(),_=a.map(t=>t.jsPath.split(".").slice(1).join(".")),i=e?.toolExecRounds??0;if(o.consoleLogs.length>0){const t=`[static_code_executor:${s.nodeDef?.id??"static_code_executor"}:${e?.threadId??"?"}]`;for(const c of o.consoleLogs)console.log(`${t} ${c}`)}return o.ok?{messages:[new g(typeof o.value=="string"?o.value:JSON.stringify(o.value??null))],toolsUsedAccum:_,toolExecRounds:i+1,codeExecTrace:a,codeExecScript:n,codeExecConsoleLogs:o.consoleLogs,codeExecStats:o.stats}:{messages:[new g(JSON.stringify({error:"TOOL_EXECUTION_FAILED",error_kind:o.error?.kind,error_message:o.error?.message}))],toolExecRounds:o.error?.kind==="syntax"?i:i+1,codeExecTrace:a,codeExecScript:n,codeExecConsoleLogs:o.consoleLogs,codeExecStats:o.stats}}export{q as execute};
@@ -0,0 +1,54 @@
1
+ import{SystemMessage as A}from"@langchain/core/messages";import{Client as B}from"@elastic/elasticsearch";import{filterNonSystemMessages as F}from"../../utils/message-utils";import{contentToString as I}from"../../utils/content-utils";import{interpolateEngineVars as D}from"../../utils/engine-vars";const H=process.env.ELASTICSEARCH_HOST||"https://51.159.174.230:9205",G=process.env.ELASTICSEARCH_USER||"elastic",q=process.env.ELASTICSEARCH_PASSWORD||"diagnostics",N=new B({node:H,auth:{username:G,password:q},tls:{rejectUnauthorized:!1}});async function J(n){try{const e=(await N.get({index:".stkxp_prompts",id:n}))._source;if(!e)return"";const o=[];e.context?.role&&o.push(e.context.role),e.behavior?.task_brief&&o.push(`
2
+ Objectif: ${e.behavior.task_brief}`),e.behavior?.detailed_instructions&&o.push(`
3
+ ${e.behavior.detailed_instructions}`),e.context?.constraints?.length&&o.push(`
4
+ Contraintes:
5
+ ${e.context.constraints.map(a=>`- ${a}`).join(`
6
+ `)}`),e.tools_policy?.tools_raw&&o.push(`
7
+ Outils disponibles: ${e.tools_policy.tools_raw}`),e.output_policy?.raw&&o.push(`
8
+ Format de sortie: ${e.output_policy.raw}`),e.error_policy?.raw&&o.push(`
9
+ Gestion d'erreurs: ${e.error_policy.raw}`),o.length===0&&(e.role&&o.push(e.role),e.task&&o.push(`
10
+ ${e.task}`),e.format&&o.push(`
11
+ ${e.format}`),e.rules&&o.push(`
12
+ ${e.rules}`),e.tools&&o.push(`
13
+ Outils disponibles:
14
+ ${e.tools}`),e.content&&e.content.trim()&&o.push(`
15
+ ${e.content}`));const r=o.join(`
16
+ `).trim();return console.log(`[System] Loaded prompt "${n}" from .stkxp_prompts (${r.length} chars)`),r}catch(m){return m?.meta?.statusCode===404?console.warn(`[System] Prompt "${n}" not found in .stkxp_prompts`):console.error(`[System] Failed to fetch prompt "${n}":`,m?.message),""}}async function W(n){try{const e=((await N.mget({index:".stkxp_resources",body:{ids:n}})).docs||[]).filter(a=>a.found).map(a=>a._source);if(e.length===0)return"";const r=`Ressources attach\xE9es:
17
+
18
+ ${e.map((a,h)=>{const t=a.title?`Resource#${h+1}: ${a.title}`:`Resource#${h+1}`,y=[a.use_case,a.description,a.prompt_text].filter(Boolean).join(`
19
+
20
+ `);return`## ${t}
21
+
22
+ ${y}`}).join(`
23
+
24
+ ---
25
+
26
+ `)}`;return console.log(`[System] Loaded ${e.length}/${n.length} attached resources (${r.length} chars)`),r}catch(m){return console.error("[System] Failed to fetch attached resources:",m?.message),""}}async function Q(n,m){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][SYSTEM]: "+JSON.stringify(n));const{graphDef:e,firstClient:o,queryParams:r,systemPrefix:a,userToken:h,assistant:t,chatId:y,channel:R}=m,k=n.messages[n.messages.length-1],j=I(k).trim();console.log("**************************system: userText",j,k);const p=n.topic||"";console.log(`[System] Using topic from state: ${p||"(none)"}`);let l="";const T=t?.promptId;let c="";if(T&&(console.log(`[System] Resolving via promptId: "${T}"`),c=await J(T)),console.log("[System] assistant context fields:",c,JSON.stringify(t)),!c&&t?.context){const s=[];if(t.context.role&&s.push(t.context.role),t.behavior?.task_brief&&s.push(`
27
+ Objectif: ${t.behavior.task_brief}`),t.behavior?.detailed_instructions&&s.push(`
28
+ ${t.behavior.detailed_instructions}`),t.context.constraints?.length&&s.push(`
29
+ Contraintes:
30
+ ${t.context.constraints.map(d=>`- ${d}`).join(`
31
+ `)}`),t.context.style){const{audience:d,tone:w,language:v}=t.context.style,E=[d&&`Audience cible: ${d}`,w&&`Ton: ${w}`,v&&`Langue: ${v}`].filter(Boolean);E.length&&s.push(`
32
+ Style:
33
+ ${E.join(`
34
+ `)}`)}t.output_policy?.raw&&s.push(`
35
+ Format de sortie: ${t.output_policy.raw}`),t.error_policy?.pseudocode&&s.push(`
36
+ Gestion d'erreurs: ${t.error_policy.pseudocode}`);const i=s.join(`
37
+ `).trim();i&&(c=i,console.log(`[System] Using assistant inline context fields (${i.length} chars)`))}const P=(t?.resources_policy?.resources||[]).map(s=>s?.id).filter(Boolean);if(P.length>0){const s=await W(P);s&&(c=c?`${c}
38
+
39
+ ${s}`:s,console.log(`[System] Appended ${P.length} attached resource(s) to assistant prompt`))}let $="";if(p&&o){const s=!a||p.startsWith(`${a}_`)?p:`${a}_${p}`;try{console.log(`[System] Resolving via MCP getPrompt: "${s}"`);const i=await o.client.getPrompt({name:s,params:{}});$=i?.messages?.[0]?.content?.[0]?.text??i?.messages?.[0]?.content?.text??i?.messages?.[0]?.content??i?.content??""}catch(i){(i instanceof Error?i.message:String(i)).includes("Unknown prompt")?console.warn(`[System] MCP prompt "${s}" not found (expected for topics outside the package \u2014 falling back to assistant prompt)`):console.error(`\u274C MCP prompt fetch failed for topic "${p}":`,i)}}const x=t?.promptCompositionMode??"replace";c?(x==="replace"?l=c:x==="prepend"?l=[c,$].filter(Boolean).join(`
40
+
41
+ `):x==="append"&&(l=[$,c].filter(Boolean).join(`
42
+
43
+ `)),console.log(`[System] compositionMode="${x}" \u2192 ${l.length} chars`)):l=$;const S=n.teamContext?`
44
+
45
+ Team Context:
46
+ ${n.teamContext}`:"",_=n.userContext?`
47
+
48
+ User Context:
49
+ ${n.userContext}`:"",L=c?l?`${l}${S}${_}`:`${S}${_}`.trim():l?`Topic: ${p}
50
+
51
+ Domain-specific context:
52
+ ${l}${S}${_}`:`Topic: ${p}${S}${_}`,O=y?`
53
+
54
+ Current chat ID: ${y}`:"",f=D(`${L}${O}`,n,{channel:R}),b=F(n.messages);console.log(`[system] Context prepared: ${f.substring(0,200)}...`),console.log(`[system] Non-system messages count: ${b.length}`);const U=n?.namespaceMap||{},C=new Set;for(const s of Object.values(U))for(const i of s||[])i?.namespace&&C.add(i.namespace);const g=r.namespace;let u;g&&C.has(g)?u=g:C.size===1?u=[...C][0]:u=g||"default",u!==g&&console.log(`[system] namespace default resolved: '${g??"(none)"}' \u2192 '${u}' (from Fleet bindings)`);const M={topic:p,mcpText:l,mandatoryParams:{userToken:h||"stkxp_session_default",namespace:u,packageName:r.packageName||"default",cluster:u,nodes:r.nodes||"",roles:r.roles||"",phases:r.phases||"hot",prefix:r.prefix||"",suffix:r.suffix||"",start:r.start||"now-4h",end:r.end||"now",interval:r.interval||"5m",topic:r.topic||"default_topic"}};return console.log("[EXECUTE][SYSTEM]",JSON.stringify({messages:[new A(f),...b],systemPromptTools:f,systemPromptFinal:f,context:M})),{messages:[new A(f),...b],systemPromptTools:f,systemPromptFinal:f,context:M}}export{Q as execute};
@@ -0,0 +1,9 @@
1
+ import{SystemMessage as R,AIMessage as b}from"@langchain/core/messages";import{createLLMInstance as I}from"../../../llm/providers";import{buildOptimizedSystemPrompt as N}from"../../../utils/prompt-optimizer";import{promptOptimizationConfig as v}from"../../../app-config/prompt-optimization";import{filterSystemMessages as P,filterNonSystemMessages as U,getNodeInstructions as D,sanitizeToolMessages as F,normalizeToolCallIds as z}from"../../utils/message-utils";import{ensureAIMessage as B}from"../../utils/content-utils";import{logNodeExecution as X,logNodeResponse as G}from"../../utils/logging-utils";import{interpolateEngineVars as H}from"../../utils/engine-vars";async function Q(e,_){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TOOL-EXECUTOR]: "+JSON.stringify(e));const{llmConfig:m,graphDef:x,tools:l,contextFromSystem:M,cfg:S,assistant:C,channel:$}=_,g=P(e.messages),n=F(U(e.messages)),A=await D(x,"assistant_tool_executor",void 0,C),p=l.map(t=>t.name).join(", ");let s=A.replace(/\$\{.*?\}/g,p).replace(/\{\{availableTools\}\}/g,p);s=H(s,e,{channel:$});const a=e?.customFields;a&&typeof a=="object"&&(s=s.replace(/%%([a-zA-Z0-9_]+)%%/g,(t,O)=>a[O]!==void 0?String(a[O]):t));const u=N({agentPrompt:s,mandatoryParams:M?.mandatoryParams||{},toolNames:l.map(t=>t.name),maxAgentPromptTokens:v.maxAgentPromptTokens}).prompt,r=g[g.length-1]?.content||"",f=e.userContext&&!String(r).includes(e.userContext)?`
2
+
3
+ User Context:
4
+ ${e.userContext}`:"",i=process.env.MAX_TOOL_ROUNDS?parseInt(process.env.MAX_TOOL_ROUNDS,10):8,E=e?.toolExecRounds??0,y=i>0&&E>=i?`
5
+
6
+ \u26A0\uFE0F You have reached the maximum number of tool-calling rounds (${i}). Do NOT call any more tools \u2014 further tool calls will not be executed. Answer now using only the information already gathered.`:"",d=r?`${r}
7
+
8
+ ${u}${f}${y}`:`${u}${f}${y}`,w=new R(d);console.log(`[assistant_tool_executor] Instructions loaded (${s.length} chars)`),console.log(`[assistant_tool_executor] Full system prompt: ${d.substring(0,200)}...`),X("TOOL EXECUTOR",m,{totalMessages:1+n.length,toolsCount:l.length});const c=I(m),L=c?.bindTools?c.bindTools(l):c;let T=n;if(n[n.length-1]?.getType()==="ai"){const{HumanMessage:t}=await import("@langchain/core/messages");T=[...n,new t("Continue with the user's request: analyze what is still needed and call the appropriate tools now.")]}const o=await L.invoke([w,...T],{configurable:S?.configurable});if(process.env.GRAPH_STATE_DEBUG){if(console.log(`
9
+ \u{1F50D} DEBUG - Raw result from llmWithTools.invoke():`),console.log(` Type: ${o?.constructor?.name||typeof o}`),console.log(` Is AIMessage: ${o instanceof b}`),console.log(` Has tool_calls: ${!!o?.tool_calls}`),console.log(` tool_calls length: ${o?.tool_calls?.length||0}`),console.log(` Has content: ${!!o?.content}`),console.log(` Content type: ${typeof o?.content}`),o?.content){const t=typeof o.content=="string"?o.content.substring(0,2e3):JSON.stringify(o.content).substring(0,2e3);console.log(` Content preview: ${t}`)}console.log("assistant_tool_executor result",o)}const h=z(B(o));return G("TOOL EXECUTOR",h),{messages:[h]}}export{Q as execute};
@@ -0,0 +1,4 @@
1
+ import{AIMessage as w}from"@langchain/core/messages";import $ from"jsonata";import{lastToolMessageContent as A,lastAIMessageContent as j,coerceToJson as _}from"../../utils/tool-result";function S(t,u,e){if(t==null)return e?"null":"";if(typeof t=="string")return e&&u==="json"?JSON.stringify(t):t;try{return JSON.stringify(t,null,2)}catch{return String(t)}}async function J(t,u){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][RAW-OUTPUT]: "+JSON.stringify(t));const{nodeDef:e}=u,i=e?.id||"raw_output";let s,n;const l=typeof e?.stateField=="string"?e.stateField.trim():"";if(l&&t?.[l]!==void 0)s=t[l],n=l;else{const o=A(t?.messages),r=j(t?.messages);if(o!==void 0&&o.trim()!=="")s=o,n="tool result";else if(r!==void 0&&r.trim()!=="")s=r,n="AI message";else if(Array.isArray(t?.teamAssistantResults)&&t.teamAssistantResults.length>0)s=t.teamAssistantResults,n="teamAssistantResults";else{const{messages:m,lastSummaryAt:R,lastToolNamesSummary:b,...y}=t||{};s=y,n="state"}}let f=s,d=!1;const a=typeof e?.jsonata=="string"?e.jsonata.trim():"";if(a){const o=_(s);if(o===void 0)console.warn(`[raw_output] ${i}: jsonata "${a}" set but source ("${n}") is not JSON-parseable \u2014 dumping raw source`);else try{const m=await $(a).evaluate(o);f=m===void 0?null:m,d=!0,console.log(`[raw_output] ${i}: applied jsonata "${a}"`)}catch(r){console.warn(`[raw_output] ${i}: jsonata eval error for "${a}": ${r?.message} \u2014 dumping raw source`)}}const c=e?.format==="text"?"text":"json",g=S(f,c,d),p=`### ${typeof e?.title=="string"&&e.title.trim()?e.title.trim():"Raw output"}
2
+
3
+ ${c==="json"?"```json\n":"```\n"}${g}
4
+ \`\`\``;return console.log(`[raw_output] ${i}: dumping "${n}" (${g.length} chars) as final ${c} block`),{messages:[new w({content:p,additional_kwargs:{__raw_output__:!0}})]}}export{J as execute};
@@ -0,0 +1,7 @@
1
+ import{SystemMessage as C}from"@langchain/core/messages";import{createLLMInstance as I}from"../../../llm/providers";import{filterSystemMessages as $,filterNonSystemMessages as D,deduplicateToolMessages as k,getNodeInstructions as b,sanitizeToolMessages as H}from"../../utils/message-utils";import{ensureAIMessage as P}from"../../utils/content-utils";import{logNodeExecution as B,logNodeResponse as x}from"../../utils/logging-utils";async function Y(r,E){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TOOL-CLEANER]: "+JSON.stringify(r));const{llmConfig:m,graphDef:L,cfg:M,assistant:T}=E,o=$(r.messages);let s=D(r.messages);s=k(s),s=H(s);const N=await b(L,"assistant_tool_cleaner",void 0,T),A=o.length>0?typeof o[0].content=="string"?o[0].content:String(o[0].content):"You are a tool result compression agent.",O=`${N}
2
+
3
+ ${A}`;B("TOOL CLEANER",m,{totalMessages:s.length});const p=s.filter(e=>e.getType()==="tool"),u=p.length;if(console.log(`\u{1F9F9} Tool messages to compress: ${u}`),u===0)return console.log("\u23ED\uFE0F No tool messages to compress, skipping..."),{messages:[]};const l=process.env.TOOL_CLEANER_MIN_CHARS?parseInt(process.env.TOOL_CLEANER_MIN_CHARS,10):24e3,f=p.reduce((e,n)=>{const c=n.content;return e+(typeof c=="string"?c.length:JSON.stringify(c).length)},0);if(l&&f<=l)return console.log(`\u23ED\uFE0F Tool payload ${f} \u2264 ${l} chars \u2014 skipping LLM compression (nothing meaningful to compress)`),{messages:[]};const S=I(m),i=[...o].reverse().find(e=>typeof e.content=="string"&&e.content.startsWith("Compressed tool results:")),y=i&&typeof i.content=="string"?i.content.replace(/^Compressed tool results:\s*/,""):"",{HumanMessage:R}=await import("@langchain/core/messages"),w=new R((y?`Running compressed summary of EARLIER tool rounds (their raw results are already pruned from history):
4
+ ${y}
5
+
6
+ `:"")+"Analyze the NEW tool results above and produce an UPDATED, CONSOLIDATED compressed summary that MERGES the earlier summary (if any) with the new findings, keeping ONLY the fields relevant to the user's original query. Output the full consolidated summary \u2014 it REPLACES the earlier one."),_=[new C(O),...s,w],a=await S.invoke(_,{configurable:M?.configurable});x("TOOL CLEANER",P(a));const{RemoveMessage:g}=await import("@langchain/core/messages"),t=[];let d=0,h=0;for(const e of r.messages){if(!e?.id)continue;const n=e.getType?.();n==="tool"?(t.push(new g({id:e.id})),d++):n==="ai"&&Array.isArray(e.tool_calls)&&e.tool_calls.length>0?(t.push(new g({id:e.id})),h++):n==="system"&&typeof e.content=="string"&&e.content.startsWith("Compressed tool results:")&&t.push(new g({id:e.id}))}const v=typeof a.content=="string"?a.content.length:0;return console.log(`\u{1F9F9} TOOL CLEANER \u2014 consolidated summary ${v} chars; pruned ${d} tool + ${h} tool-call message(s) (input no longer re-grows each round). `+(t.length===0?"\u26A0\uFE0F 0 removals \u2014 messages lacked ids; raw results NOT pruned (falling back to append-only).":"")),{messages:[...t,new C(`Compressed tool results:
7
+ ${a.content}`)]}}export{Y as execute};
@@ -0,0 +1,3 @@
1
+ import{ToolMessage as m}from"@langchain/core/messages";import{interrupt as _}from"@langchain/langgraph";import{buildFormBlockFromTool as $}from"../../../../utils/tool-form-trigger";import{invokeWithTimeout as O}from"./invoke";import{capToolResultContent as w}from"./result-limits";async function y(t,a,d,i){const c=a.find(r=>r.name===t.name),u=Date.now();if(!c)return console.log(`[Tool Node] \u274C Tool not found: ${t.name}`),new m({tool_call_id:t.id,content:JSON.stringify({error:"Tool not found",tool_name:t.name})});try{const r=i??t.args,o=await O(c,r,d,t.name),e=Date.now()-u;if(console.log(`
2
+ ${"\u{1F4E6} ".repeat(40)}`),console.log(`\u{1F4E6} TOOL NODE - Result received from ${t.name}`),console.log(`${"\u{1F4E6} ".repeat(40)}`),console.log(`\u23F1\uFE0F Duration: ${e}ms`),o&&typeof o=="object"&&o.error==="RESULT_TOO_LARGE")console.log("\u{1F6A8} GUARDED RESULT DETECTED - Result too large!"),console.log(` Approx tokens: ${o.approx_tokens}`),console.log(` Max allowed: ${o.max_allowed_tokens}`),o.suggestion&&console.log(` Suggestion: "${o.suggestion.substring(0,150)}${o.suggestion.length>150?"...":""}"`);else{console.log("\u2705 Normal result - No size issues");const g=typeof o=="string"?o.length:JSON.stringify(o).length;console.log(` Result size: ${g} chars`)}console.log(`${"\u{1F4E6} ".repeat(40)}
3
+ `);const l=typeof o=="string"?o:JSON.stringify(o),s=w(l,t.name);return console.log(`\u{1F4DD} Creating ToolMessage with tool_call_id: ${t.id}`),console.log(` Content length: ${s.length} chars`),new m({tool_call_id:t.id,content:s})}catch(r){const o=Date.now()-u;return console.log(`[Tool Node] \u274C ${t.name} failed after ${o}ms: ${r.message}`),new m({tool_call_id:t.id,content:JSON.stringify({error:"TOOL_EXECUTION_FAILED",tool_name:t.name,error_message:r.message})})}}async function C(t){const{toolCalls:a,skipped:d,finalTools:i,cfg:c,maxParallel:u}=t,r=a.some(e=>i.find(s=>s.name===e.name)?._requiresForm===!0);let o;if(r){console.log("[Tool Node] \u{1F512} Form-gated tools detected \u2014 switching to sequential execution"),o=[];for(const e of a){const l=i.find(s=>s.name===e.name);if(l?._requiresForm&&l?._toolDoc){const s=$(l._toolDoc);console.log(`[Tool Node] \u23F8 Interrupting for form gate: ${e.name}`);const g=_({type:"form",message:`Param\xE8tres requis pour : ${l._toolDoc.label??l._toolDoc.name??e.name}`,payload:s});if(!g?.approved){console.log(`[Tool Node] \u{1F6AB} Form cancelled by user for: ${e.name}`),o.push(new m({tool_call_id:e.id,content:JSON.stringify({cancelled:!0,tool:e.name})}));continue}console.log(`[Tool Node] \u2705 Form approved, executing ${e.name} with user values`),o.push(await y(e,i,c,g.values??e.args))}else o.push(await y(e,i,c))}}else{const e=n=>`${n.name}::${JSON.stringify(n.args)}`,l=new Map;for(const n of a)l.has(e(n))||l.set(e(n),n);const s=a.length-l.size;s>0&&console.log(`[Tool Node] \u{1FA9E} Deduplicated ${s} identical tool call(s) \u2014 executing ${l.size} unique of ${a.length}`);const g=await Promise.allSettled([...l.entries()].map(async([n,f])=>{const p=await y(f,i,c);return[n,p]})),T=new Map;for(const n of g)n.status==="fulfilled"&&T.set(n.value[0],n.value[1]);o=a.map(n=>{const f=T.get(e(n)),p=f?f.content:JSON.stringify({error:"TOOL_EXECUTION_FAILED",tool_name:n.name});return new m({tool_call_id:n.id,content:p})})}for(const e of d)console.log(`[Tool Node] \u23ED\uFE0F Skipped: ${e.name}`),o.push(new m({tool_call_id:e.id,content:JSON.stringify({error:"TOOL_EXECUTION_SKIPPED",tool_name:e.name,reason:`MAX_PARALLEL_TOOLS=${u}`})}));return o}export{C as executeToolCalls};
@@ -0,0 +1 @@
1
+ const a=process.env.TOOL_INVOKE_TIMEOUT_MS?parseInt(process.env.TOOL_INVOKE_TIMEOUT_MS,10):2e5;async function u(o,s,e,t){if(!a)return o.invoke(s,e);const i=o.invoke(s,e);return console.log("[invokeWithTimeout] Invoking tool",t,"with timeout",a,"ms"),i.catch?.(()=>{}),Promise.race([i,new Promise((c,n)=>setTimeout(()=>n(new Error(`Tool '${t}' exceeded TOOL_INVOKE_TIMEOUT_MS=${a}ms`)),a))])}async function _(o,s,e={}){const t=e.retries??3,i=e.baseDelayMs??800,c=new Set(e.retryOn??[429,502,503,504]);for(let n=0;n<=t;n++)try{return await o.invoke(s)}catch(r){const O=r?.status??r?.code??r?.response?.status;if(!(c.has(Number(O))||r?.name==="TimeoutError")||n===t)throw r;const m=i*Math.pow(2,n);await new Promise(y=>setTimeout(y,m))}}export{a as TOOL_INVOKE_TIMEOUT_MS,u as invokeWithTimeout,_ as safeInvoke};
@@ -0,0 +1 @@
1
+ function $(a){return typeof a=="string"?a:Array.isArray(a)?a.map(n=>typeof n=="string"?n:n?.text??"").join(" "):""}function S(a){if(a&&typeof a=="object"){if(typeof a.namespace=="string")return{namespaceValue:a.namespace,via:"field"};if(typeof a.input=="string")try{const n=JSON.parse(a.input);if(n&&typeof n=="object")return{namespaceValue:typeof n.namespace=="string"?n.namespace:void 0,via:"input",parsedInput:n}}catch{}}return{via:"none"}}function N(a){const n=a?.schema||a?.inputSchema;if(!n)return!0;const i=n.shape&&typeof n.shape=="object"?Object.keys(n.shape):n.properties&&typeof n.properties=="object"?Object.keys(n.properties):null;return i===null?!0:i.includes("namespace")}function v(a,n,i){if(n.via==="input"){const m={...n.parsedInput||{},namespace:i};return{...a,input:JSON.stringify(m)}}return{...a,namespace:i}}function T(a){const{toolCalls:n,finalTools:i,namespaceMap:m,messages:f}=a,p={};for(const[e,t]of Object.entries(m||{})){const o=new Set;for(const s of t||[])s?.namespace&&o.add(s.namespace);p[e.toLowerCase()]=o}const l=new Set(Object.keys(p)),d=[...f||[]].reverse().find(e=>e?.getType?.()==="human"||e?._getType?.()==="human"||e?.role==="user"),g=$(d?.content).toLowerCase();if(process.env.GRAPH_STATE_DEBUG&&console.log(`[Tool Node] \u{1F6E1}\uFE0F guard DEBUG: systemKeys=[${[...l].join(",")}] | toolCalls=[${n.map(e=>e.name).join(",")}] | finalTools=${JSON.stringify(i.map(e=>({name:e?.name,_system:e?._system,_mcpServerName:e?._mcpServerName,_mcpServerId:e?._mcpServerId})))}`),l.size>0)for(const e of n){const t=i.find(u=>u.name===e.name),o=t?._system||t?._mcpServerName;if(console.log(`[Tool Node] \u{1F6E1}\uFE0F guard DEBUG: toolCall="${e.name}" matched=${!!t} _system=${t?._system} _mcpServerName=${t?._mcpServerName} => toolSystem=${o} | args=${JSON.stringify(e.args).slice(0,200)}`),!o){console.warn(`[Tool Node] \u{1F6E1}\uFE0F namespace guard: SKIP ${e.name} \u2014 no _system/_mcpServerName tag (tool wrapping may have stripped it). matched=${!!t}`);continue}if(!N(t)){console.warn(`[Tool Node] \u{1F6E1}\uFE0F namespace guard: SKIP ${e.name} \u2014 tool has no 'namespace' param (toolSystem="${o}"); not an Elastic-namespaced tool.`);continue}const s=p[String(o).toLowerCase()];if(!s||s.size===0){console.warn(`[Tool Node] \u{1F6E1}\uFE0F namespace guard: no namespaces for ${e.name} (toolSystem="${o}") \u2014 map keys=[${[...l].join(",")}]`);continue}const y=S(e.args),c=y.namespaceValue;if(c&&s.has(c))continue;let r;s.size===1?r=[...s][0]:r=[...s].find(u=>g.includes(u.toLowerCase())),r&&r!==c?(e.args=v(e.args,y,r),console.log(`[Tool Node] \u{1F6E1}\uFE0F namespace guard: '${c??"(missing)"}' \u2192 '${r}' for ${e.name} (system="${o}")`+(s.size>1?` (picked from user question among ${s.size} candidates)`:""))):r||console.warn(`[Tool Node] \u26A0\uFE0F namespace guard: '${c??"(missing)"}' invalid for ${e.name} (system="${o}") \u2014 ${s.size} candidates [${[...s].join(", ")}], none named in the user's question; leaving as-is.`)}}export{T as applyNamespaceGuard};
@@ -0,0 +1,3 @@
1
+ import{truncateUtf16Safe as s}from"../../../../utils/text-utils";const r=process.env.MAX_TOOL_RESULT_CHARS?parseInt(process.env.MAX_TOOL_RESULT_CHARS,10):16e3;function n(e,o){if(!r||e.length<=r)return e;const t=e.length-r;return console.log(`[Tool Node] \u2702\uFE0F Capped ${o} result: ${e.length} \u2192 ${r} chars (${t} omitted)`),s(e,r)+`
2
+
3
+ \u2026[truncated ${t} of ${e.length} chars by MAX_TOOL_RESULT_CHARS=${r}. This tool result was too large to send in full \u2014 narrow the query (shorter time range; filter by cluster/app/host; fewer fields) to retrieve complete data.]`}export{r as MAX_TOOL_RESULT_CHARS,n as capToolResultContent};
@@ -0,0 +1 @@
1
+ import{AIMessage as A}from"@langchain/core/messages";function k(e){const t=[...e||[]].reverse().find(n=>n?.getType?.()==="human"||n?._getType?.()==="human"||n?.role==="user")?.content;return typeof t=="string"?t:Array.isArray(t)?t.map(n=>typeof n=="string"?n:n?.text??"").join(" "):""}function N(e,r){const t=/\{\{([#^])\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}([\s\S]*?)\{\{\/\s*\2\s*\}\}/;let n=e,a=0;for(;t.test(n)&&a<100;)n=n.replace(t,(o,s,c,l)=>{const f=r(c);return(s==="#"?f:!f)?l:""}),a+=1;return n}function w(e){return e==null?"":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):JSON.stringify(e)}function m(e){if(e)return e.typeName==="ZodOptional"||e.typeName==="ZodDefault"?m(e.innerType?._def):e.typeName}function b(e,r){if(!r?.schema)return e;let t;try{typeof r.schema._def?.shape=="function"&&(t=r.schema._def.shape())}catch{}if(!t)return e;const n={...e};for(const[a,o]of Object.entries(n)){if(typeof o!="string")continue;const s=t[a]?._def,c=m(s);if(c==="ZodNumber"){const l=Number(o);isNaN(l)||(n[a]=l)}else c==="ZodBoolean"&&(o==="true"||o==="1"?n[a]=!0:(o==="false"||o==="0")&&(n[a]=!1))}return n}function u(e,r){if(Array.isArray(e))return e.map(o=>u(o,r));if(e&&typeof e=="object"){const o={};for(const[s,c]of Object.entries(e))o[s]=u(c,r);return o}if(typeof e!="string")return e;const t=e.trim().match(/^\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}$/);if(t){const o=t[1];return o in r?r[o]:""}return N(e,o=>{const s=r[o];return s==null?!1:typeof s=="string"?s.trim()!=="":Array.isArray(s)?s.length>0:!0}).replace(/\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g,(o,s)=>w(r[s]))}async function $(e,r){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TOOL-INVOKER]: "+JSON.stringify(e));const{nodeDef:t,tools:n}=r,a=Array.isArray(t?.toolCalls)&&t.toolCalls.length>0?t.toolCalls:[{toolName:t?.toolName,argsMapping:t?.argsMapping}],o=k(e.messages),s={input:o,query:o,...e?.variables&&typeof e.variables=="object"?e.variables:{},...e?.toolArgs&&typeof e.toolArgs=="object"?e.toolArgs:{},...e?.context&&typeof e.context=="object"?e.context:{},__username:r.deps?.username,__teamId:r.deps?.teamId,__chatId:r.deps?.chatId},c=new Set((n||[]).map(i=>i.name)),l=t?.id||"tool_invoker",f=e?.messages?.length??0,g=a.filter(i=>i?.toolName?(c.has(i.toolName)||console.warn(`[tool_invoker] ${l}: tool "${i.toolName}" is not in the available tool set ([${[...c].slice(0,20).join(", ")}${c.size>20?", \u2026":""}]). Check the assistant's mcp_servers_policy.`),!0):(console.warn(`[tool_invoker] ${l}: skipping spec with no toolName`),!1)).map((i,p)=>{const y=u(i.argsMapping??{},s)??{},d=(n||[]).find(h=>h.name===i.toolName),_=b(y,d);return{id:`${l}_${f}_${p}`,name:i.toolName,args:_,type:"tool_call"}});return console.log(`[tool_invoker] ${l}: emitting ${g.length} deterministic tool_call(s): `+g.map(i=>`${i.name}(${JSON.stringify(i.args).slice(0,120)})`).join(", ")),{messages:[new A({content:"",tool_calls:g})]}}export{$ as execute};
@@ -0,0 +1,4 @@
1
+ import{applyNamespaceGuard as L}from"./tool-execution/namespace-guard";import{executeToolCalls as S}from"./tool-execution/execute-tool-calls";import{safeInvoke as M}from"./tool-execution/invoke";function y(e){if(!e)return;const r=/_(\d+)_(\d+)$/.exec(e);return r?e.slice(0,r.index):void 0}async function x(e,r){process.env.GRAPH_STATE_DEBUG&&console.log("[STATE][TOOL]: "+JSON.stringify(e));const{finalTools:g,cfg:d}=r;process.env.GRAPH_STATE_DEBUG&&(console.log("[Tool Node] \u{1F527} State :",e),console.log("[Tool Node] \u{1F527} Config :",d));const s=e.messages[e.messages.length-1];if(s.invalid_tool_calls?.length>0&&console.error("\u274C FINAL message has invalid tool calls:",JSON.stringify(s.invalid_tool_calls,null,2)),s.tool_calls?.length>0&&console.log("\u2705 Valid tool calls:",s.tool_calls),!s||s.getType()!=="ai"||!s.tool_calls?.length)return console.log("[Tool Node] No tool calls found in last message."),{messages:[]};const n=process.env.MAX_PARALLEL_TOOLS?parseInt(process.env.MAX_PARALLEL_TOOLS,10):void 0,t=n?s.tool_calls.slice(0,n):s.tool_calls,m=n?s.tool_calls.slice(n):[];console.log(`[Tool Node] \u{1F527} Executing ${t.length} tool(s) in parallel${n?` (max=${n})`:""}:`),t.forEach((l,o)=>console.log(` ${o+1}. ${l.name}`));const T=Date.now();L({toolCalls:t,finalTools:g,namespaceMap:e?.namespaceMap||{},messages:e.messages});const a=await S({toolCalls:t,skipped:m,finalTools:g,cfg:d,maxParallel:n}),_=Date.now()-T;console.log(`[Tool Node] \u{1F3AF} All tools completed in ${_}ms (parallel execution)`),console.log(`
2
+ ${"\u{1F4CA} ".repeat(40)}`),console.log("\u{1F4CA} TOOL NODE - Final Summary"),console.log(`${"\u{1F4CA} ".repeat(40)}`),console.log(`\u2705 Total ToolMessages: ${a.length}`);let u=0,f=0,p=0,c=0;a.forEach(l=>{try{const o=JSON.parse(l.content);o.error==="RESULT_TOO_LARGE"?u++:o.error==="TOOL_EXECUTION_FAILED"?f++:o.error==="TOOL_EXECUTION_SKIPPED"?p++:c++}catch{c++}}),console.log(`
3
+ \u{1F4C8} Breakdown:`),console.log(` \u2705 Successful: ${c}`),console.log(` \u{1F6A8} Guarded (too large): ${u}`),console.log(` \u274C Failed: ${f}`),console.log(` \u23ED\uFE0F Skipped: ${p}`),console.log(`${"\u{1F4CA} ".repeat(40)}
4
+ `);const E=a.some(l=>{try{const o=JSON.parse(l.content);return!!(o?.error&&o.error!=="RESULT_TOO_LARGE")}catch{return!1}}),O=(e?.toolExecRounds??0)+1,A=[...new Set(t.map(l=>l.name).filter(Boolean))],i={};return a.forEach(l=>{const o=y(l.tool_call_id);if(o)try{i[o]=JSON.parse(l.content)}catch{i[o]=l.content}}),{messages:a,last_tool_error:E,toolExecRounds:O,toolsUsedAccum:A,toolResults:i}}export{x as execute,M as safeInvoke};
@@ -0,0 +1 @@
1
+ function r(n){try{const e=n.schema?._def?.shape();e?console.log(`[SCHEMA] ${n.name} keys:`,Object.keys(e)):console.log(`[SCHEMA] ${n.name} schema:`,JSON.stringify(n))}catch{console.log(`[SCHEMA] ${n.name} (no shape introspection)`)}}function a(n){try{const e=n?._def?.shape?.();return e?Object.keys(e):[]}catch{return[]}}function i(n){let e=n;if(typeof e=="string")try{e=JSON.parse(e)}catch{}return e&&typeof e=="object"&&("apiKey"in e&&!("api_key"in e)&&(e.api_key=e.apiKey,delete e.apiKey),"userName"in e&&!("username"in e)&&(e.username=e.userName,delete e.userName),"pass"in e&&!("password"in e)&&(e.password=e.pass,delete e.pass)),e}function y(n,e){const s=new Set(a(e));if(!s.size||typeof n!="object"||!n)return n;const o={};for(const t of Object.keys(n))s.has(t)&&(o[t]=n[t]);return o}export{y as filterArgsToSchema,a as getAllowedKeysFromZod,i as normalizeArgs,r as tryLogSchema};
@@ -0,0 +1 @@
1
+ import{createLLMInstance as u}from"../llm/providers";import{z as d}from"zod";import{getABEvaluator as x}from"../utils/ab-evaluator";const g=new Map;function T(s,e){g.set(s,e)}function E(s){for(const[,e]of g)if(!(!e||e==="unknown"))try{if(new RegExp(`\\b(${e})\\b`,"i").test(s))return console.log(`[TOPIC-DYNAMIC] Matched dynamic pattern "${e}"`),e}catch{}return null}const w=d.object({topic:d.enum(["clusters_clusters_overview","clusters_clusters_health-check","clusters_clusters_finops","clusters_nodes_inventory","clusters_nodes_operations","clusters_nodes_storage","clusters_nodes_resources","clusters_nodes_shards","clusters_nodes_thread_pool","clusters_nodes_tasks","clusters_nodes_hot_threads","clusters_jobs_enrich","clusters_jobs_snapshots","clusters_indices_inventory","clusters_indices_operations","clusters_indices_storage","clusters_indices_segments","clusters_indices_documents","elasticsearch_doc","mysql_mysql_overview","platform.core.execute_esql"])});async function p(s,e,o){const t=await u({...e,streaming:!1,temperature:0}).withStructuredOutput(w).withConfig({tags:["nostream"]}).invoke([{role:"system",content:o},{role:"user",content:s}]);return console.log("generateTopicWithLLM",JSON.stringify(t)),t.topic}async function M(s,e){const n=await u({...e,streaming:!1,temperature:0}).withConfig({tags:["nostream"]}).invoke([{role:"system",content:`Extract salient search keywords and the language of the user's message. Keywords should be terms someone would search a catalog with to find something relevant to this message \u2014 not a paraphrase of the message itself. Respond with ONLY a JSON object, no other text: {"keywords": string[], "language": string}. language is the ISO 639-1 code of the message (e.g. "en", "fr").`},{role:"user",content:s}]),t=typeof n.content=="string"?n.content:JSON.stringify(n.content),c=t.match(/\{[\s\S]*\}/);if(!c)return console.warn(`[extractKeywordsAndLanguage] No JSON object found in LLM response: ${t.slice(0,200)}`),{keywords:[],language:"en"};try{const i=JSON.parse(c[0]);return{keywords:Array.isArray(i.keywords)?i.keywords.map(String):[],language:typeof i.language=="string"?i.language:"en"}}catch(i){return console.warn(`[extractKeywordsAndLanguage] Malformed JSON in LLM response: ${i.message}`),{keywords:[],language:"en"}}}function _(s){const e=s.toLowerCase(),o=[{regex:/cluster.*health|health.*cluster|cluster.*status/i,topic:"clusters_clusters_health-check"},{regex:/\b(red|yellow|green)\s+(cluster|status)/i,topic:"clusters_clusters_health-check"},{regex:/\b(cost|price|pricing|finops|billing|expense)/i,topic:"clusters_cluster_finops"},{regex:/\b(list|show|display|get)\s+(all\s+)?nodes/i,topic:"clusters_nodes_inventory"},{regex:/nodes?\s+(list|inventory)/i,topic:"clusters_nodes_inventory"},{regex:/nodes?\s+(operations?|tasks?|running)/i,topic:"clusters_nodes_operations"},{regex:/what.*nodes.*doing|nodes.*activity/i,topic:"clusters_nodes_operations"},{regex:/\b(disk|storage|space|capacity)\b/i,topic:"clusters_nodes_storage"},{regex:/disk\s+(usage|used|free|space)/i,topic:"clusters_nodes_storage"},{regex:/\b(cpu|memory|ram|resources?)\b/i,topic:"clusters_nodes_resources"},{regex:/nodes?\s+(cpu|memory|resources)/i,topic:"clusters_nodes_resources"},{regex:/\b(shards?|shard\s+allocation|unassigned)/i,topic:"clusters_nodes_shards"},{regex:/\b(thread\s?pool|threads?|queue)/i,topic:"clusters_nodes_thread_pool"},{regex:/hot\s?threads?/i,topic:"clusters_nodes_hot_threads"},{regex:/\b(enrich|enrichment)\b/i,topic:"clusters_jobs_enrich"},{regex:/\b(snapshot|backup|restore)/i,topic:"clusters_jobs_snapshots"},{regex:/\b(list|show|display|get)\s+(all\s+)?ind(ice|ex)s?/i,topic:"clusters_indices_inventory"},{regex:/ind(ice|ex)s?\s+(list|inventory)/i,topic:"clusters_indices_inventory"},{regex:/ind(ice|ex)s?\s+(operations?|stats?|performance)/i,topic:"clusters_indices_operations"},{regex:/ind(ice|ex)s?\s+(size|storage|disk)/i,topic:"clusters_indices_storage"},{regex:/\b(segments?|segment\s+count)/i,topic:"clusters_indices_segments"},{regex:/\b(documents?|doc\s+count|indexing\s+rate)/i,topic:"clusters_indices_documents"},{regex:/\b(elasticsearch|es)\s+(doc|documentation|guide|help)/i,topic:"elasticsearch_doc"},{regex:/how\s+to.*elasticsearch/i,topic:"elasticsearch_doc"},{regex:/\bmysql\b/i,topic:"mysql_mysql_overview"},{regex:/\besql\b|es\|ql/i,topic:"platform.core.execute_esql"}];for(const r of o)if(r.regex.test(e))return console.log(`[TOPIC-REGEXP] Matched: ${r.topic} (pattern: ${r.regex})`),r.topic;return console.log("[TOPIC-REGEXP] No match found, using default: clusters_clusters_overview"),"clusters_clusters_overview"}async function b(s,e,o){const r=s.toLowerCase();function n(a,h){const m=[{keywords:["cluster","health"],topic:"clusters_clusters_health-check",confidence:95},{keywords:["list","nodes"],topic:"clusters_nodes_inventory",confidence:95},{keywords:["disk","space"],topic:"clusters_nodes_storage",confidence:90},{keywords:["cost","price"],topic:"clusters_cluster_finops",confidence:90},{keywords:["snapshot","backup"],topic:"clusters_jobs_snapshots",confidence:90}];for(const l of m)if(l.topic===h&&l.keywords.every(f=>a.includes(f)))return l.confidence;const y=["health","cost","disk","snapshot","shard","thread"];for(const l of y)if(a.includes(l))return 70;return a.includes("or")||a.includes("maybe")||a.includes("?")?40:55}const t=_(s),c=n(r,t),i=Number(process.env.AB_CONFIDENCE_THRESHOLD)||80;if(c>=i)return console.log(`[TOPIC-HYBRID] High confidence (${c}%) - Using RegExp: ${t}`),t;console.log(`[TOPIC-HYBRID] Low confidence (${c}%) - Falling back to LLM`);try{return await p(s,e,o)}catch(a){return console.error(`[TOPIC-HYBRID] LLM topic detection failed, falling back to RegExp guess "${t}":`,a),t}}async function O(s,e,o){const r=x(),n=Number(process.env.AB_TEST_ITERATIONS)||5,t=Number(process.env.AB_TEST_WARMUP)||1;return await r.runWithSelection({testId:"topic-generation",variants:[{id:"llm-current",name:"LLM Structured Output (current)",description:"Uses LLM with structured output for topic generation",implementation:async()=>p(s,e,o),enabled:!0},{id:"regexp",name:"RegExp Pattern Matching",description:"Uses regex patterns for ultra-fast topic detection",implementation:()=>Promise.resolve(_(s)),enabled:!0},{id:"hybrid",name:"Hybrid (RegExp + LLM fallback)",description:"Uses RegExp when confident, falls back to LLM otherwise",implementation:async()=>b(s,e,o),enabled:!0}],defaultVariantId:"llm-current",iterations:n,warmupRuns:t},async c=>await c.implementation())}export{M as extractKeywordsAndLanguage,b as generateTopicHybrid,p as generateTopicWithLLM,_ as generateTopicWithRegExp,T as registerAssistantTopic,E as resolveTopicByRegExp,O as runTopicABTest};
@@ -0,0 +1 @@
1
+ const n=["threadId","queryParams","userToken","username","teamId","teamSharedContext","chatId","memoryScoped","rawUserInput","webhookDepth","channel"];function a(t){const e={};for(const r of n)e[r]=t[r];return e}export{n as TEAM_FORWARD_KEYS,a as forwardTeamDeps};
@@ -0,0 +1,17 @@
1
+ import{AIMessage as d}from"@langchain/core/messages";import{createLLMInstance as O}from"../../llm/providers";function $(e){const t=e?.content;if(typeof t=="string")return t;if(Array.isArray(t)){const r=t.find(i=>typeof i?.text=="string")?.text;if(r)return r}return t?.toString?.()??""}function S(e){return Math.ceil(e.length/4)}const M=process.env.TOOL_RESULT_MAX_TOKENS?parseInt(process.env.TOOL_RESULT_MAX_TOKENS,10):4e3;function k(e){if(!e)return{data:[]};if(Array.isArray(e?.data))return{data:e.data,nextCursor:e.nextCursor,meta:e.meta};if(Array.isArray(e?.result?.data))return{data:e.result.data,nextCursor:e.nextCursor??e.result?.nextCursor,meta:e.result?.meta};const t=e.nextCursor||e?.aggregations?.by_namespace?.buckets?.[0]?.g?.after_key;return{data:[],nextCursor:t}}async function R(e,t,r,i,f={}){const{maxTokens:o=M,sampleItems:y=20}=f,x=JSON.stringify(e),s=S(x);if(console.log(`
2
+ `+"\u{1F6E1}\uFE0F ".repeat(40)),console.log(`\u{1F6E1}\uFE0F GUARDED TOOL RESULT - ${t}`),console.log("\u{1F6E1}\uFE0F ".repeat(40)),console.log(`\u{1F4CA} Total tokens: ${s}`),console.log(`\u2696\uFE0F Max allowed: ${o}`),console.log(`\u2705 Within limits: ${s<=o?"YES":"NO"}`),s<=o)return console.log("\u2705 Result size OK - passing through without modification"),console.log("\u{1F6E1}\uFE0F ".repeat(40)+`
3
+ `),e;const{data:a,meta:l}=k(e),n=Array.isArray(a)?a.slice(0,y):void 0,u=Array.isArray(a)?a.length:0;console.log(`\u274C Result too large by ${s-o} tokens`),console.log(`\u{1F4E6} Data items: ${u}`),console.log(`\u{1F50D} Sample items: ${n?.length||0}`),console.log("\u{1F916} Generating LLM fallback suggestion..."),console.log(` Tool: ${t}`),console.log(` Args: ${JSON.stringify(r).substring(0,100)}...`);try{const c=O({...i,temperature:.7,maxTokens:500}),g=`L'utilisateur a ex\xE9cut\xE9 un outil qui a retourn\xE9 un r\xE9sultat trop volumineux (${s} tokens).
4
+
5
+ Outil: ${t}
6
+ Param\xE8tres utilis\xE9s: ${JSON.stringify(r,null,2)}
7
+ M\xE9tadonn\xE9es: ${JSON.stringify(l,null,2)}
8
+ \xC9chantillon de donn\xE9es (${n?.length||0} items): ${JSON.stringify(n?.slice(0,3),null,2)}
9
+
10
+ G\xE9n\xE8re un message court et constructif (2-3 phrases max) qui :
11
+ 1. Explique pourquoi le r\xE9sultat est trop large
12
+ 2. Propose des suggestions CONCR\xC8TES pour affiner la requ\xEAte (r\xE9duire la p\xE9riode, ajouter des filtres, limiter le scope)
13
+ 3. Utilise un ton amical et encourageant
14
+
15
+ Message:`,{SystemMessage:_,HumanMessage:T}=await import("@langchain/core/messages"),p=await c.invoke([new _("Tu es un assistant qui aide les utilisateurs \xE0 affiner leurs requ\xEAtes pour obtenir des r\xE9sultats plus cibl\xE9s. R\xE9ponds de fa\xE7on concise et constructive en fran\xE7ais."),new T(g)]),m=typeof p.content=="string"?p.content:String(p.content);console.log("\u2705 LLM suggestion generated successfully!"),console.log(`\u{1F4DD} Suggestion: "${m.substring(0,150)}${m.length>150?"...":""}"`);const L={error:"RESULT_TOO_LARGE",approx_tokens:s,max_allowed_tokens:o,suggestion:m,meta:{...l,has_sample:!!n,data_count:u},sample:n};return console.log("\u{1F6E1}\uFE0F ".repeat(40)+`
16
+ `),L}catch(c){console.error(`\u274C Failed to generate LLM suggestion: ${c.message}`);const g={error:"RESULT_TOO_LARGE",approx_tokens:s,max_allowed_tokens:o,suggestion:"Le r\xE9sultat est trop volumineux. Essayez de r\xE9duire la p\xE9riode de temps (par exemple: 1h au lieu de 24h), d'ajouter des filtres plus sp\xE9cifiques (namespace, nodes, roles), ou de limiter le nombre de r\xE9sultats.",meta:{...l,has_sample:!!n,data_count:u},sample:n};return console.log("\u{1F6E1}\uFE0F ".repeat(40)+`
17
+ `),g}}function E(e){if(e instanceof d)return e;const t=typeof e?.content=="string"?e.content:e?.content||"";return new d({content:t,tool_calls:e?.tool_calls||[],additional_kwargs:e?.additional_kwargs||{},response_metadata:e?.response_metadata||{}})}export{M as TOOL_RESULT_MAX_TOKENS,R as buildGuardedToolResult,$ as contentToString,E as ensureAIMessage,S as estimateTokens,k as mapToolOutput};