@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.
- package/README.md +273 -0
- package/bin/stkxp.mjs +198 -0
- package/package.json +97 -0
- package/src/bootstrap.mjs +37 -0
- package/src/bootstrap.test.mjs +73 -0
- package/src/deploy.mjs +145 -0
- package/src/deploy.test.mjs +131 -0
- package/src/export.mjs +30 -0
- package/src/export.test.mjs +56 -0
- package/src/secret-input.mjs +64 -0
- package/src/secret-input.test.mjs +58 -0
- package/src/serve.mjs +83 -0
- package/src/serve.test.mjs +93 -0
- package/vendor/dist-server/asyncapi/generator.js +1 -0
- package/vendor/dist-server/asyncapi/messages.js +1 -0
- package/vendor/dist-server/asyncapi/viewer.html +43 -0
- package/vendor/dist-server/core/app-config/branding.js +1 -0
- package/vendor/dist-server/core/app-config/mantine-theme.js +1 -0
- package/vendor/dist-server/core/app-config/mermaid-theme.js +2 -0
- package/vendor/dist-server/core/app-config/prompt-optimization.js +1 -0
- package/vendor/dist-server/core/app-config/settings.js +1 -0
- package/vendor/dist-server/core/config.js +1 -0
- package/vendor/dist-server/core/graph/a2a-agent-executor.js +2 -0
- package/vendor/dist-server/core/graph/app.js +120 -0
- package/vendor/dist-server/core/graph/delegated-agent-adapter.js +1 -0
- package/vendor/dist-server/core/graph/graph-builder.js +3 -0
- package/vendor/dist-server/core/graph/kibana-agent-executor.js +1 -0
- package/vendor/dist-server/core/graph/nodes/context/assistants-context.js +5 -0
- package/vendor/dist-server/core/graph/nodes/context/compare-context.js +10 -0
- package/vendor/dist-server/core/graph/nodes/context/enrich-context.js +8 -0
- package/vendor/dist-server/core/graph/nodes/context/inventory-context.js +4 -0
- package/vendor/dist-server/core/graph/nodes/context/namespace-context.js +2 -0
- package/vendor/dist-server/core/graph/nodes/context/node-types-context.js +4 -0
- package/vendor/dist-server/core/graph/nodes/context/relevant-assistants-context.js +5 -0
- package/vendor/dist-server/core/graph/nodes/context/relevant-skills-context.js +5 -0
- package/vendor/dist-server/core/graph/nodes/context/skills-context.js +8 -0
- package/vendor/dist-server/core/graph/nodes/context/state-setter.js +1 -0
- package/vendor/dist-server/core/graph/nodes/control/check-reset.js +1 -0
- package/vendor/dist-server/core/graph/nodes/control/topic-detection.js +1 -0
- package/vendor/dist-server/core/graph/nodes/governance/human-approval.js +16 -0
- package/vendor/dist-server/core/graph/nodes/index.js +1 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/suggestion-generator.js +17 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-decider.js +1 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/decider-error.js +4 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/decider-standalone-runner.js +1 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/decider-synthesis.js +29 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/pipeline-memory.js +2 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/pipeline-runner.js +7 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-execution/team-assistant-utils.js +1 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-finder.js +13 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-invoker.js +3 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-parallel.js +1 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-pipeline.js +6 -0
- package/vendor/dist-server/core/graph/nodes/orchestration/team-router.js +26 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/code-executor/index.js +6 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/code-executor/resource-bridge.js +2 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/code-executor/sandbox.js +6 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/code-executor/tool-bridge.js +1 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/local-extractor.js +5 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/response-generator.js +47 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/static-code-executor/index.js +1 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/system.js +54 -0
- package/vendor/dist-server/core/graph/nodes/reasoning/tool-executor.js +9 -0
- package/vendor/dist-server/core/graph/nodes/tools/raw-output.js +4 -0
- package/vendor/dist-server/core/graph/nodes/tools/tool-cleaner.js +7 -0
- package/vendor/dist-server/core/graph/nodes/tools/tool-execution/execute-tool-calls.js +3 -0
- package/vendor/dist-server/core/graph/nodes/tools/tool-execution/invoke.js +1 -0
- package/vendor/dist-server/core/graph/nodes/tools/tool-execution/namespace-guard.js +1 -0
- package/vendor/dist-server/core/graph/nodes/tools/tool-execution/result-limits.js +3 -0
- package/vendor/dist-server/core/graph/nodes/tools/tool-invoker.js +1 -0
- package/vendor/dist-server/core/graph/nodes/tools/tool.js +4 -0
- package/vendor/dist-server/core/graph/schemas.js +1 -0
- package/vendor/dist-server/core/graph/topic-variants.js +1 -0
- package/vendor/dist-server/core/graph/types.js +1 -0
- package/vendor/dist-server/core/graph/utils/content-utils.js +17 -0
- package/vendor/dist-server/core/graph/utils/edge-jsonata-condition.js +1 -0
- package/vendor/dist-server/core/graph/utils/engine-vars.js +1 -0
- package/vendor/dist-server/core/graph/utils/logging-utils.js +4 -0
- package/vendor/dist-server/core/graph/utils/message-utils.js +5 -0
- package/vendor/dist-server/core/graph/utils/node-type-defaults-cache.js +1 -0
- package/vendor/dist-server/core/graph/utils/sandbox-catalog.js +1 -0
- package/vendor/dist-server/core/graph/utils/schema-utils.js +1 -0
- package/vendor/dist-server/core/graph/utils/team-context-policy.js +5 -0
- package/vendor/dist-server/core/graph/utils/team-node-resolvers.js +1 -0
- package/vendor/dist-server/core/graph/utils/tool-result.js +4 -0
- package/vendor/dist-server/core/graph/utils/tool-wrapper.js +14 -0
- package/vendor/dist-server/core/llm/init-indices.js +1 -0
- package/vendor/dist-server/core/llm/models/index.js +1 -0
- package/vendor/dist-server/core/llm/models/model.model.js +1 -0
- package/vendor/dist-server/core/llm/models/provider.model.js +1 -0
- package/vendor/dist-server/core/llm/models/routing-rule.model.js +1 -0
- package/vendor/dist-server/core/llm/providers.js +1 -0
- package/vendor/dist-server/core/mcp/client.js +1 -0
- package/vendor/dist-server/core/runtime/active-runs-registry.js +1 -0
- package/vendor/dist-server/core/runtime/system-prompt-cache.js +1 -0
- package/vendor/dist-server/core/runtime/trace-bus.js +1 -0
- package/vendor/dist-server/core/schema/cluster_health_report.js +1 -0
- package/vendor/dist-server/core/schema/cluster_info.js +1 -0
- package/vendor/dist-server/core/schema/cluster_license.js +5 -0
- package/vendor/dist-server/core/schema/cluster_stats.js +12 -0
- package/vendor/dist-server/core/schema/dashboard.js +1 -0
- package/vendor/dist-server/core/schema/indices_settings.js +1 -0
- package/vendor/dist-server/core/schema/indices_shards.js +1 -0
- package/vendor/dist-server/core/schema/indices_stats.js +1 -0
- package/vendor/dist-server/core/schema/nodes_info.js +2 -0
- package/vendor/dist-server/core/schema/nodes_stats.js +11 -0
- package/vendor/dist-server/core/schema/pricing.js +1 -0
- package/vendor/dist-server/core/schema/ui.js +1 -0
- package/vendor/dist-server/core/schema/zod_client.js +83 -0
- package/vendor/dist-server/core/services/a2a-client.js +2 -0
- package/vendor/dist-server/core/services/alerts-service.js +1 -0
- package/vendor/dist-server/core/services/api-keys-service.js +1 -0
- package/vendor/dist-server/core/services/assistant-resolver.js +1 -0
- package/vendor/dist-server/core/services/assistants-index-service.js +1 -0
- package/vendor/dist-server/core/services/async-conversations-service.js +22 -0
- package/vendor/dist-server/core/services/asyncapi-dispatch.js +1 -0
- package/vendor/dist-server/core/services/asyncapi-drivers/driver-manager.js +1 -0
- package/vendor/dist-server/core/services/asyncapi-drivers/driver-types.js +0 -0
- package/vendor/dist-server/core/services/asyncapi-drivers/http-driver.js +1 -0
- package/vendor/dist-server/core/services/asyncapi-drivers/nats-driver.js +1 -0
- package/vendor/dist-server/core/services/asyncapi-drivers/websocket-driver.js +1 -0
- package/vendor/dist-server/core/services/asyncapi-events-service.js +1 -0
- package/vendor/dist-server/core/services/asyncapi-reply-service.js +1 -0
- package/vendor/dist-server/core/services/asyncapi-sink.js +1 -0
- package/vendor/dist-server/core/services/asyncapi-tools-service.js +1 -0
- package/vendor/dist-server/core/services/block-repair-service.js +13 -0
- package/vendor/dist-server/core/services/chart-renderer.js +1 -0
- package/vendor/dist-server/core/services/chat-llms-service.js +1 -0
- package/vendor/dist-server/core/services/chat-runs-service.js +1 -0
- package/vendor/dist-server/core/services/chat-tools-service.js +1 -0
- package/vendor/dist-server/core/services/chat-traces-service.js +1 -0
- package/vendor/dist-server/core/services/chats-service.js +5 -0
- package/vendor/dist-server/core/services/comparison-service.js +107 -0
- package/vendor/dist-server/core/services/default-model.service.js +1 -0
- package/vendor/dist-server/core/services/elastic-stack-sync-service.js +2 -0
- package/vendor/dist-server/core/services/elasticsearch-wrapper.js +1 -0
- package/vendor/dist-server/core/services/embed-rate-limiter.js +1 -0
- package/vendor/dist-server/core/services/error-analytics-service.js +1 -0
- package/vendor/dist-server/core/services/es-field-resolver.js +1 -0
- package/vendor/dist-server/core/services/gateway-platform-types.js +1 -0
- package/vendor/dist-server/core/services/gliner-tagging-service.js +1 -0
- package/vendor/dist-server/core/services/golden-questions-scoring.js +1 -0
- package/vendor/dist-server/core/services/golden-questions-service.js +1 -0
- package/vendor/dist-server/core/services/graph-drilldown-service.js +1 -0
- package/vendor/dist-server/core/services/graph-registry-service.js +1 -0
- package/vendor/dist-server/core/services/hitl-analytics-service.js +1 -0
- package/vendor/dist-server/core/services/ingestion-jobs-service.js +1 -0
- package/vendor/dist-server/core/services/ingestion-service.js +5 -0
- package/vendor/dist-server/core/services/kibana-client-factory.js +1 -0
- package/vendor/dist-server/core/services/kibana-client.js +2 -0
- package/vendor/dist-server/core/services/kibana-dashboard-extractor.js +1 -0
- package/vendor/dist-server/core/services/kibana-service.js +1 -0
- package/vendor/dist-server/core/services/llm-analytics-service.js +1 -0
- package/vendor/dist-server/core/services/llm-client-resolver.js +1 -0
- package/vendor/dist-server/core/services/llm-models-service.js +1 -0
- package/vendor/dist-server/core/services/llm-pricing-pure.js +1 -0
- package/vendor/dist-server/core/services/llm-pricing-service.js +1 -0
- package/vendor/dist-server/core/services/llm-providers-service.js +1 -0
- package/vendor/dist-server/core/services/llm-routing-service.js +1 -0
- package/vendor/dist-server/core/services/llm-services.js +1 -0
- package/vendor/dist-server/core/services/llm-sync-service.js +1 -0
- package/vendor/dist-server/core/services/manifest-loader.js +1 -0
- package/vendor/dist-server/core/services/mcp-servers-service.js +1 -0
- package/vendor/dist-server/core/services/mcp-sync-service.js +1 -0
- package/vendor/dist-server/core/services/mcp-tools-service.js +1 -0
- package/vendor/dist-server/core/services/memories-service.js +2 -0
- package/vendor/dist-server/core/services/memory-analytics-service.js +1 -0
- package/vendor/dist-server/core/services/monitoring-analytics-service.js +1 -0
- package/vendor/dist-server/core/services/monitoring-service.js +1 -0
- package/vendor/dist-server/core/services/multi-kibana-service.js +1 -0
- package/vendor/dist-server/core/services/node-latency-service.js +1 -0
- package/vendor/dist-server/core/services/package-policy-service.js +2 -0
- package/vendor/dist-server/core/services/pdf-service.js +572 -0
- package/vendor/dist-server/core/services/plan-service.js +1 -0
- package/vendor/dist-server/core/services/platform-direction.js +1 -0
- package/vendor/dist-server/core/services/platform-secrets.js +1 -0
- package/vendor/dist-server/core/services/platforms-service.js +1 -0
- package/vendor/dist-server/core/services/policy-factory.js +1 -0
- package/vendor/dist-server/core/services/prompt-cache-service.js +1 -0
- package/vendor/dist-server/core/services/provider-rate-limits.js +1 -0
- package/vendor/dist-server/core/services/quota-service.js +1 -0
- package/vendor/dist-server/core/services/report-assets-service.js +1 -0
- package/vendor/dist-server/core/services/run-analytics-collector.js +1 -0
- package/vendor/dist-server/core/services/run-stream-sink.js +1 -0
- package/vendor/dist-server/core/services/send_mail.js +460 -0
- package/vendor/dist-server/core/services/share-service.js +1 -0
- package/vendor/dist-server/core/services/slack-signature.js +1 -0
- package/vendor/dist-server/core/services/sources-service.js +6 -0
- package/vendor/dist-server/core/services/team-mcp-result.js +4 -0
- package/vendor/dist-server/core/services/team-mcp-run-tokens.js +1 -0
- package/vendor/dist-server/core/services/team-mcp-runner.js +1 -0
- package/vendor/dist-server/core/services/team-mcp-server.js +1 -0
- package/vendor/dist-server/core/services/team-mcp-tools.js +1 -0
- package/vendor/dist-server/core/services/team-mcp-ui.js +551 -0
- package/vendor/dist-server/core/services/team-run-progress.js +1 -0
- package/vendor/dist-server/core/services/team-runner-headless.js +7 -0
- package/vendor/dist-server/core/services/team-search-service.js +1 -0
- package/vendor/dist-server/core/services/teams-service.js +1 -0
- package/vendor/dist-server/core/services/token-projection-service.js +1 -0
- package/vendor/dist-server/core/services/tool-analytics-service.js +1 -0
- package/vendor/dist-server/core/services/tool-history-service.js +1 -0
- package/vendor/dist-server/core/services/tool-metrics-service.js +1 -0
- package/vendor/dist-server/core/services/tool-scoring.js +1 -0
- package/vendor/dist-server/core/services/toolbox-import-mappers.js +1 -0
- package/vendor/dist-server/core/services/toolbox-import-service.js +1 -0
- package/vendor/dist-server/core/services/trigger-service.js +1 -0
- package/vendor/dist-server/core/services/version-snapshot-service.js +1 -0
- package/vendor/dist-server/core/services/webhook-calls-service.js +1 -0
- package/vendor/dist-server/core/tools/compare-chat.js +46 -0
- package/vendor/dist-server/core/tools/enrich-chat.js +50 -0
- package/vendor/dist-server/core/tools/variable-encoding.js +1 -0
- package/vendor/dist-server/core/types/settings.js +1 -0
- package/vendor/dist-server/core/utils/ab-evaluator.js +5 -0
- package/vendor/dist-server/core/utils/condition-evaluator.js +1 -0
- package/vendor/dist-server/core/utils/http-client.js +1 -0
- package/vendor/dist-server/core/utils/json-schema-to-form.js +1 -0
- package/vendor/dist-server/core/utils/logger.js +3 -0
- package/vendor/dist-server/core/utils/owner-scope.js +1 -0
- package/vendor/dist-server/core/utils/ownership.js +1 -0
- package/vendor/dist-server/core/utils/parallel-tool-executor.js +1 -0
- package/vendor/dist-server/core/utils/performance-tracker.js +3 -0
- package/vendor/dist-server/core/utils/prompt-optimizer.js +40 -0
- package/vendor/dist-server/core/utils/response-cache.js +1 -0
- package/vendor/dist-server/core/utils/schema-validator.js +1 -0
- package/vendor/dist-server/core/utils/streaming-optimizer.js +2 -0
- package/vendor/dist-server/core/utils/string-helpers.js +1 -0
- package/vendor/dist-server/core/utils/test-responses.js +9 -0
- package/vendor/dist-server/core/utils/text-utils.js +1 -0
- package/vendor/dist-server/core/utils/tool-form-trigger.js +1 -0
- package/vendor/dist-server/entrypoints/cli-bootstrap-run.js +1 -0
- package/vendor/dist-server/entrypoints/cli-deploy-run.js +1 -0
- package/vendor/dist-server/entrypoints/cli-deploy.js +1 -0
- package/vendor/dist-server/entrypoints/team-runner.js +1 -0
- package/vendor/dist-server/generated/toolbox-catalog.js +1 -0
- package/vendor/dist-server/index.js +2 -0
- package/vendor/dist-server/middleware/integration-logos.js +1 -0
- package/vendor/dist-server/middleware/plan-guard.js +1 -0
- package/vendor/dist-server/openapi/generator.js +1 -0
- package/vendor/dist-server/openapi/html-tool-spec.js +1 -0
- package/vendor/dist-server/routes/a2a-routes.js +1 -0
- package/vendor/dist-server/routes/a2a-server-routes.js +5 -0
- package/vendor/dist-server/routes/admin.js +1 -0
- package/vendor/dist-server/routes/assistants-routes.js +1 -0
- package/vendor/dist-server/routes/asyncapi-routes.js +1 -0
- package/vendor/dist-server/routes/auth.js +1 -0
- package/vendor/dist-server/routes/billing-routes.js +1 -0
- package/vendor/dist-server/routes/chat-llms.js +1 -0
- package/vendor/dist-server/routes/chat-tools.js +1 -0
- package/vendor/dist-server/routes/chat-traces.js +1 -0
- package/vendor/dist-server/routes/chats.js +1 -0
- package/vendor/dist-server/routes/clusters.js +1 -0
- package/vendor/dist-server/routes/compare.js +43 -0
- package/vendor/dist-server/routes/connectors-routes.js +1 -0
- package/vendor/dist-server/routes/consumptions-routes.js +1 -0
- package/vendor/dist-server/routes/data-admin-routes.js +1 -0
- package/vendor/dist-server/routes/data-transfer-routes.js +1 -0
- package/vendor/dist-server/routes/elastic-tool-execution-routes.js +1 -0
- package/vendor/dist-server/routes/geo-proxy-routes.js +1 -0
- package/vendor/dist-server/routes/golden-questions-routes.js +1 -0
- package/vendor/dist-server/routes/graph-registry.js +1 -0
- package/vendor/dist-server/routes/graph-templates-routes.js +1 -0
- package/vendor/dist-server/routes/helpdesk-routes.js +35 -0
- package/vendor/dist-server/routes/html-routes.js +1 -0
- package/vendor/dist-server/routes/index.js +1 -0
- package/vendor/dist-server/routes/indices.js +1 -0
- package/vendor/dist-server/routes/integrations-routes.js +1 -0
- package/vendor/dist-server/routes/langgraph.js +7 -0
- package/vendor/dist-server/routes/live-resources-routes.js +1 -0
- package/vendor/dist-server/routes/llm-analytics.js +1 -0
- package/vendor/dist-server/routes/llm-control-plane.js +1 -0
- package/vendor/dist-server/routes/llm.js +1 -0
- package/vendor/dist-server/routes/mcp-gateway-routes.js +1 -0
- package/vendor/dist-server/routes/mcp-query-routes.js +1 -0
- package/vendor/dist-server/routes/mcp-servers-routes.js +1 -0
- package/vendor/dist-server/routes/mcp-team-routes.js +1 -0
- package/vendor/dist-server/routes/mcp-tools-routes.js +1 -0
- package/vendor/dist-server/routes/me-routes.js +63 -0
- package/vendor/dist-server/routes/memories-routes.js +1 -0
- package/vendor/dist-server/routes/monitoring-analytics.js +12 -0
- package/vendor/dist-server/routes/monitoring.js +1 -0
- package/vendor/dist-server/routes/node-types-routes.js +171 -0
- package/vendor/dist-server/routes/nodes.js +1 -0
- package/vendor/dist-server/routes/packages.js +1 -0
- package/vendor/dist-server/routes/pdf.js +3 -0
- package/vendor/dist-server/routes/plan-routes.js +1 -0
- package/vendor/dist-server/routes/platform-requests-routes.js +1 -0
- package/vendor/dist-server/routes/platforms-routes.js +1 -0
- package/vendor/dist-server/routes/prompts-routes.js +1 -0
- package/vendor/dist-server/routes/proxy-logos.js +1 -0
- package/vendor/dist-server/routes/quality-routes.js +1 -0
- package/vendor/dist-server/routes/resources-ingest-routes.js +1 -0
- package/vendor/dist-server/routes/resources-routes.js +1 -0
- package/vendor/dist-server/routes/schema-routes.js +1 -0
- package/vendor/dist-server/routes/settings-original.js +1 -0
- package/vendor/dist-server/routes/settings.js +1 -0
- package/vendor/dist-server/routes/share-routes.js +1 -0
- package/vendor/dist-server/routes/sources-catalog-routes.js +1 -0
- package/vendor/dist-server/routes/sources-routes.js +1 -0
- package/vendor/dist-server/routes/team-optimizer-routes.js +1 -0
- package/vendor/dist-server/routes/team-schedule-routes.js +1 -0
- package/vendor/dist-server/routes/teams-routes.js +1 -0
- package/vendor/dist-server/routes/tool-analytics.js +1 -0
- package/vendor/dist-server/routes/tool-history-routes.js +1 -0
- package/vendor/dist-server/routes/tool-metrics-routes.js +1 -0
- package/vendor/dist-server/routes/toolbox-import-routes.js +1 -0
- package/vendor/dist-server/routes/tools-routes.js +5 -0
- package/vendor/dist-server/routes/transcribe-routes.js +1 -0
- package/vendor/dist-server/routes/triggers.js +1 -0
- package/vendor/dist-server/routes/versions-routes.js +1 -0
- package/vendor/dist-server/routes/webhooks-routes.js +1 -0
- package/vendor/dist-server/scripts/add-label-to-tools.js +4 -0
- package/vendor/dist-server/scripts/migrate-assistants-to-mcp.js +10 -0
- package/vendor/dist-server/scripts/migrate-chat-runs.js +8 -0
- package/vendor/dist-server/scripts/migrate-mcp-protocol.js +8 -0
- package/vendor/dist-server/scripts/migrate-mcp-to-platforms.js +15 -0
- package/vendor/dist-server/services/alert-evaluator.js +3 -0
- package/vendor/dist-server/services/auth.js +1 -0
- package/vendor/dist-server/services/billing-service.js +1 -0
- package/vendor/dist-server/services/chat-title-generator.js +12 -0
- package/vendor/dist-server/services/clone/clone-executor.js +1 -0
- package/vendor/dist-server/services/clone/closure-resolver.js +3 -0
- package/vendor/dist-server/services/clone/entity-graph.js +3 -0
- package/vendor/dist-server/services/clone/team-bundle-bootstrap.js +1 -0
- package/vendor/dist-server/services/clone/team-bundle-crypto.js +1 -0
- package/vendor/dist-server/services/clone/team-bundle-encrypted.js +1 -0
- package/vendor/dist-server/services/clone/team-bundle.js +1 -0
- package/vendor/dist-server/services/cluster-service.js +1 -0
- package/vendor/dist-server/services/connection-adapters.js +1 -0
- package/vendor/dist-server/services/connectors-service.js +10 -0
- package/vendor/dist-server/services/cost-forecast-service.js +1 -0
- package/vendor/dist-server/services/eui-ssr-renderer.js +4 -0
- package/vendor/dist-server/services/graph-canvas/full-structure-builder.js +1 -0
- package/vendor/dist-server/services/graph-templates-service.js +13 -0
- package/vendor/dist-server/services/guest-service.js +1 -0
- package/vendor/dist-server/services/html-service.js +1 -0
- package/vendor/dist-server/services/langgraph-service.js +2 -0
- package/vendor/dist-server/services/leaflet-render-service.js +80 -0
- package/vendor/dist-server/services/live-resources-service.js +16 -0
- package/vendor/dist-server/services/mcp-app-tester-package.js +1 -0
- package/vendor/dist-server/services/mcp-gateway/executors/openapi-executor.js +1 -0
- package/vendor/dist-server/services/mcp-gateway/gateway-grant-service.js +2 -0
- package/vendor/dist-server/services/team-optimizer-service.js +1 -0
- package/vendor/dist-server/services/trace-bus-sink.js +1 -0
- package/vendor/dist-server/services/user-provisioning-service.js +3 -0
- package/vendor/dist-server/templates/mcp-app-tester/src/mcp-http.js +3 -0
- package/vendor/dist-server/templates/mcp-app-tester/src/server.js +1 -0
- package/vendor/dist-server/utils.js +1 -0
- package/vendor/dist-server/ws/assistant-executor.js +7 -0
- package/vendor/dist-server/ws/classify-streamed-json-block.js +1 -0
- package/vendor/dist-server/ws/collect-response-generator-node-ids.js +1 -0
- package/vendor/dist-server/ws/extractors/blockkit-extractor.js +1 -0
- package/vendor/dist-server/ws/extractors/echarts-extractor.js +1 -0
- package/vendor/dist-server/ws/extractors/eui-extractor.js +1 -0
- package/vendor/dist-server/ws/extractors/form-extractor.js +1 -0
- package/vendor/dist-server/ws/extractors/index.js +1 -0
- package/vendor/dist-server/ws/extractors/leaflet-extractor.js +1 -0
- package/vendor/dist-server/ws/extractors/mantine-extractor.js +1 -0
- package/vendor/dist-server/ws/extractors/markdown-extractor.js +7 -0
- package/vendor/dist-server/ws/extractors/mermaid-extractor.js +1 -0
- package/vendor/dist-server/ws/extractors/recharts-extractor.js +1 -0
- package/vendor/dist-server/ws/extractors/remotion-extractor.js +1 -0
- package/vendor/dist-server/ws/handler.js +66 -0
- package/vendor/dist-server/ws/parsers/anthropic-parser.js +7 -0
- package/vendor/dist-server/ws/parsers/base-parser.js +3 -0
- package/vendor/dist-server/ws/parsers/gemini-parser.js +8 -0
- package/vendor/dist-server/ws/parsers/index.js +1 -0
- package/vendor/dist-server/ws/parsers/parse-json-blocks.js +1 -0
- package/vendor/dist-server/ws/types.js +0 -0
- package/vendor/dist-server/ws/utils.js +1 -0
- package/vendor/shared/engine-vars.ts +51 -0
- package/vendor/shared/llm-providers-config.ts +69 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{McpServer as y}from"@modelcontextprotocol/sdk/server/mcp.js";import{z as t}from"zod";import{randomUUID as h}from"crypto";import{buildTeamToolDescriptors as S}from"./team-mcp-tools";import{startMcpTeamRun as I}from"./team-mcp-runner";import{readTeamRunResult as R,mapRunResultToToolResult as m,mapAskOpenToToolResult as k}from"./team-mcp-result";import{registerTeamUiResource as x,TEAM_UI_TOOL_META as u,TEAM_UI_RESOURCE_URI as p}from"./team-mcp-ui";import{getChatRunByRunId as _}from"./chat-runs-service";import{getChatById as v}from"./chats-service";const O={getChatRunByRunId:e=>_(e),getChatById:(e,n)=>v(e,n)};async function D(e){const n=new y({name:`stkxp-team-${e.id}`,version:"1.0.0"},{capabilities:{tools:{},resources:{}}});x(n);const d=S(e,{exposeAssistants:!!e.mcpExposeAssistants}),l={message:t.string().describe("The question or task for the team"),context:t.record(t.any()).optional().describe("Optional structured context")},g={runToken:t.string(),message:t.string(),context:t.record(t.any()).optional()},T={runToken:t.string().describe("Idempotency token from the ask_ tool result"),message:t.string().describe("The original question or task for the team"),context:t.record(t.any()).optional().describe("Optional structured context")},c={runId:t.string(),status:t.enum(["running","completed","error"]),text:t.string().optional(),blocks:t.array(t.any()).optional(),error:t.string().optional()},f={runId:t.string().describe("runId returned by start_team_run / shown in the card")};for(const r of d)r.kind==="team"?n.registerTool(r.name,{description:r.description,inputSchema:l,outputSchema:g,annotations:{readOnlyHint:!1,destructiveHint:!1,openWorldHint:!0},_meta:u},async({message:o,context:s})=>{const a=h();return k({runToken:a,message:o,context:s},p)}):r.kind==="start_run"?n.registerTool(r.name,{description:r.description,inputSchema:T,outputSchema:c,annotations:{readOnlyHint:!1,destructiveHint:!1,openWorldHint:!0},_meta:u},async({runToken:o,message:s,context:a})=>{try{const{runId:i}=await I({teamId:e.id,message:s,context:a,team:e,runToken:o});return m({runId:i,status:"running"},p)}catch(i){return{content:[{type:"text",text:`Failed to start team run: ${i?.message??i}`}],isError:!0}}}):r.kind==="get_run"?n.registerTool(r.name,{description:r.description,inputSchema:f,outputSchema:c,annotations:{readOnlyHint:!0,destructiveHint:!1,openWorldHint:!1},_meta:u},async({runId:o})=>{const s=await R(o,e.owner??"unknown",O);return m(s,p)}):console.log(`[MCP-Team] Skipping assistant tool "${r.name}" \u2014 per-assistant execution is a follow-up plan`);return n}function F(e){}export{D as getOrCreateTeamMcpServer,F as invalidateTeamMcpServer};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function u(t){const e=(t??"").toLowerCase().replace(/[^a-z0-9_-]+/g,"_").replace(/_+/g,"_").replace(/^[_-]+|[_-]+$/g,"");return(e.length>0?e:"tool").slice(0,64)}function i(t,e){if(!e.has(t))return e.add(t),t;let a=2;for(;;){const s=`_${a}`;let n;if(t.length+s.length<=64)n=t+s;else{const o=Math.max(1,64-s.length);n=(t.slice(0,o)+s).replace(/[_-]+$/,"")}if(!e.has(n))return e.add(n),n;a+=1}}function p(t,e){const a=new Set,s=[],n=t.name||"team",o=i(`ask_${u(n)}`,a),l=(t.assistants??[]).map(r=>r?.name).filter(Boolean).join(", ");return s.push({kind:"team",name:o,description:`Ask the "${n}" team. ${t.description??""}`.trim()+(l?` Assistants: ${l}.`:"")+" Runs the team's full coordination graph and returns a synthesized answer."}),s.push({kind:"start_run",name:i("start_team_run",a),description:"Internal: launch the team run behind the interactive run card. The ask_ tool returns a runToken; the card calls this with that runToken plus the original message. Not intended for direct model use."}),e.exposeAssistants&&(t.assistants??[]).forEach((r,c)=>{const d=r?.name||`assistant ${c+1}`;s.push({kind:"assistant",name:i(`ask_${u(d)}`,a),description:`Ask "${d}" directly (single assistant of the "${n}" team). `+(r?.description??""),assistantId:r?.id,assistantIndex:c})}),s.push({kind:"get_run",name:i("get_team_run",a),description:"Fetch the result of a team run started earlier (async fallback). Pass the runId returned by an ask_ tool."}),s}export{p as buildTeamToolDescriptors,u as sanitizeToolName};
|
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
const t="text/html;profile=mcp-app",e="ui://stkxp/team-run.html",r="1.7.4",n={resourceDomains:["https://esm.sh","https://tile.openstreetmap.org","https://*.tile.openstreetmap.org","https://api.mapbox.com"],connectDomains:["https://esm.sh","https://france-geojson.gregoiredavid.fr","https://raw.githubusercontent.com"]},a=`<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<link rel="stylesheet" href="https://esm.sh/leaflet@1.9.4/dist/leaflet.css" />
|
|
7
|
+
<style>
|
|
8
|
+
:root { color-scheme: light dark; }
|
|
9
|
+
body {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 12px 14px;
|
|
12
|
+
font-family: var(--font-sans, system-ui, -apple-system, "Segoe UI", sans-serif);
|
|
13
|
+
font-size: var(--font-text-md-size, 14px);
|
|
14
|
+
color: var(--color-text-primary, #1a1c21);
|
|
15
|
+
background: var(--color-background-primary, #ffffff);
|
|
16
|
+
}
|
|
17
|
+
h1, h2, h3 { color: var(--color-text-primary, #1a1c21); margin: 0.6em 0 0.3em; }
|
|
18
|
+
.stkxp-status { font-size: 12px; color: var(--color-text-secondary, #69707d); margin-bottom: 8px; }
|
|
19
|
+
.stkxp-status.error { color: var(--color-text-danger, #bd271e); }
|
|
20
|
+
.stkxp-block { margin: 14px 0; }
|
|
21
|
+
.stkxp-block-title { font-weight: var(--font-weight-semibold, 600); margin-bottom: 4px; }
|
|
22
|
+
.stkxp-block-desc { font-size: 12px; color: var(--color-text-secondary, #69707d); margin-bottom: 6px; }
|
|
23
|
+
.stkxp-chart { width: 100%; height: 320px; }
|
|
24
|
+
.stkxp-map { width: 100%; border-radius: var(--border-radius-md, 6px); overflow: hidden; }
|
|
25
|
+
.stkxp-map .leaflet-container { background: var(--color-background-secondary, #f5f7fa); }
|
|
26
|
+
table.stkxp-table { border-collapse: collapse; width: 100%; font-size: 13px; }
|
|
27
|
+
table.stkxp-table th, table.stkxp-table td {
|
|
28
|
+
border: 1px solid var(--color-border-primary, #d3dae6);
|
|
29
|
+
padding: 6px 8px; text-align: left;
|
|
30
|
+
}
|
|
31
|
+
table.stkxp-table th { background: var(--color-background-secondary, #f5f7fa); font-weight: 600; }
|
|
32
|
+
pre.stkxp-raw {
|
|
33
|
+
background: var(--color-background-secondary, #f5f7fa);
|
|
34
|
+
padding: 8px; border-radius: var(--border-radius-md, 6px);
|
|
35
|
+
overflow: auto; font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px;
|
|
36
|
+
}
|
|
37
|
+
a { color: var(--color-text-info, #0077cc); }
|
|
38
|
+
.stkxp-loading { display: flex; align-items: center; gap: 10px; padding: 18px 4px; color: var(--color-text-secondary, #69707d); }
|
|
39
|
+
.stkxp-spinner {
|
|
40
|
+
width: 20px; height: 20px; flex: 0 0 auto;
|
|
41
|
+
border: 2.5px solid var(--color-border-primary, #d3dae6);
|
|
42
|
+
border-top-color: var(--color-text-info, #0077cc);
|
|
43
|
+
border-radius: 50%;
|
|
44
|
+
animation: stkxp-spin 0.8s linear infinite;
|
|
45
|
+
}
|
|
46
|
+
@keyframes stkxp-spin { to { transform: rotate(360deg); } }
|
|
47
|
+
.stkxp-loading-text { font-size: 13px; }
|
|
48
|
+
.stkxp-loading-sub { font-size: 11px; opacity: 0.8; }
|
|
49
|
+
</style>
|
|
50
|
+
</head>
|
|
51
|
+
<body>
|
|
52
|
+
<div id="probe" style="font-size:12px;margin-bottom:8px;font-weight:600;"></div>
|
|
53
|
+
<div id="root"><div class="stkxp-status">Waiting for team result\u2026</div></div>
|
|
54
|
+
<script type="module">
|
|
55
|
+
import { App } from "https://esm.sh/@modelcontextprotocol/ext-apps@${r}/app-with-deps";
|
|
56
|
+
import { marked } from "https://esm.sh/marked@12";
|
|
57
|
+
import * as echarts from "https://esm.sh/echarts@5";
|
|
58
|
+
import mermaid from "https://esm.sh/mermaid@11";
|
|
59
|
+
import L from "https://esm.sh/leaflet@1.9.4";
|
|
60
|
+
|
|
61
|
+
mermaid.initialize({ startOnLoad: false, theme: "default", securityLevel: "strict" });
|
|
62
|
+
|
|
63
|
+
const root = document.getElementById("root");
|
|
64
|
+
const statusLine = document.getElementById("probe");
|
|
65
|
+
|
|
66
|
+
// Error/status banner outside #root so render() never wipes it.
|
|
67
|
+
function showStatus(message, isError) {
|
|
68
|
+
if (!statusLine) return;
|
|
69
|
+
statusLine.textContent = message;
|
|
70
|
+
statusLine.style.color = isError ? "#bd271e" : "#69707d";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let mermaidSeq = 0;
|
|
74
|
+
let runStartMs = null; // when the current run's loading state began
|
|
75
|
+
let elapsedNode = null; // sub-line showing elapsed seconds
|
|
76
|
+
|
|
77
|
+
function el(tag, className) {
|
|
78
|
+
const node = document.createElement(tag);
|
|
79
|
+
if (className) node.className = className;
|
|
80
|
+
return node;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function updateElapsed() {
|
|
84
|
+
if (!elapsedNode || runStartMs == null) return;
|
|
85
|
+
const secs = Math.round((Date.now() - runStartMs) / 1000);
|
|
86
|
+
elapsedNode.textContent = "Refreshing automatically \xB7 " + secs + "s elapsed";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Animated spinner + elapsed counter while the team run is still going. The
|
|
90
|
+
// poll loop does NOT re-render this (so the CSS spin stays smooth); only the
|
|
91
|
+
// elapsed sub-line is updated in place by a 1s ticker.
|
|
92
|
+
function renderLoading(result) {
|
|
93
|
+
root.innerHTML = "";
|
|
94
|
+
if (runStartMs == null) runStartMs = Date.now();
|
|
95
|
+
const wrap = el("div", "stkxp-loading");
|
|
96
|
+
const spinner = el("div", "stkxp-spinner");
|
|
97
|
+
const textWrap = el("div");
|
|
98
|
+
const line1 = el("div", "stkxp-loading-text");
|
|
99
|
+
line1.textContent = "\u23F3 Team run in progress\u2026";
|
|
100
|
+
elapsedNode = el("div", "stkxp-loading-sub");
|
|
101
|
+
updateElapsed();
|
|
102
|
+
textWrap.appendChild(line1);
|
|
103
|
+
textWrap.appendChild(elapsedNode);
|
|
104
|
+
wrap.appendChild(spinner);
|
|
105
|
+
wrap.appendChild(textWrap);
|
|
106
|
+
root.appendChild(wrap);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function renderMarkdown(container, mdText) {
|
|
110
|
+
const wrap = el("div", "stkxp-markdown");
|
|
111
|
+
wrap.innerHTML = marked.parse(String(mdText ?? ""), { breaks: true });
|
|
112
|
+
container.appendChild(wrap);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function renderTitleAndDesc(container, block) {
|
|
116
|
+
if (block.title) {
|
|
117
|
+
const titleNode = el("div", "stkxp-block-title");
|
|
118
|
+
titleNode.textContent = block.title;
|
|
119
|
+
container.appendChild(titleNode);
|
|
120
|
+
}
|
|
121
|
+
if (block.description) {
|
|
122
|
+
const descNode = el("div", "stkxp-block-desc");
|
|
123
|
+
descNode.textContent = block.description;
|
|
124
|
+
container.appendChild(descNode);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Teardrop pin as an inline SVG divIcon \u2014 avoids leaflet's default marker
|
|
129
|
+
// PNGs (whose relative CSS paths break when the lib is loaded from a CDN).
|
|
130
|
+
// Mirrors makeSvgIcon in the app's native LeafletRenderer.
|
|
131
|
+
function makeLeafletIcon(color) {
|
|
132
|
+
const svg =
|
|
133
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 36" width="24" height="36">' +
|
|
134
|
+
'<path fill="' + color + '" stroke="white" stroke-width="1.5" ' +
|
|
135
|
+
'd="M12 0C7.6 0 4 3.6 4 8c0 5.4 8 28 8 28s8-22.6 8-28c0-4.4-3.6-8-8-8z"/>' +
|
|
136
|
+
'<circle fill="white" cx="12" cy="8" r="3"/></svg>';
|
|
137
|
+
return L.divIcon({ html: svg, iconSize: [24, 36], iconAnchor: [12, 36], popupAnchor: [0, -36], className: "" });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Renders a leaflet map block: base tiles + markers/circles/polylines/polygons,
|
|
141
|
+
// plus optional choropleth (fetch geojson_url, join data_join by key, shade by
|
|
142
|
+
// choropleth.property). Defaults mirror the app's native LeafletRenderer.
|
|
143
|
+
function renderLeaflet(container, block) {
|
|
144
|
+
const mapNode = el("div", "stkxp-map");
|
|
145
|
+
mapNode.style.height = (block.height != null ? block.height : 400) + "px";
|
|
146
|
+
container.appendChild(mapNode);
|
|
147
|
+
// Leaflet needs the node in the DOM with a measurable size before init.
|
|
148
|
+
root.appendChild(container);
|
|
149
|
+
|
|
150
|
+
let map;
|
|
151
|
+
try {
|
|
152
|
+
const isMapbox = block.tileLayer === "mapbox" && block.mapboxToken;
|
|
153
|
+
const tileUrl = isMapbox
|
|
154
|
+
? "https://api.mapbox.com/styles/v1/mapbox/" + (block.mapboxStyle || "streets-v12") +
|
|
155
|
+
"/tiles/{z}/{x}/{y}?access_token=" + block.mapboxToken
|
|
156
|
+
: "https://tile.openstreetmap.org/{z}/{x}/{y}.png";
|
|
157
|
+
const attribution = isMapbox
|
|
158
|
+
? '\xA9 <a href="https://www.mapbox.com/about/maps/">Mapbox</a> \xA9 <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
|
159
|
+
: '\xA9 <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
|
|
160
|
+
|
|
161
|
+
map = L.map(mapNode, { scrollWheelZoom: false });
|
|
162
|
+
map.setView(block.center || [0, 0], block.zoom != null ? block.zoom : 5);
|
|
163
|
+
L.tileLayer(tileUrl, { attribution, crossOrigin: true }).addTo(map);
|
|
164
|
+
|
|
165
|
+
(block.markers || []).forEach((mk) => {
|
|
166
|
+
const marker = L.marker([mk.lat, mk.lng], { icon: makeLeafletIcon(mk.color || "#0077CC") });
|
|
167
|
+
if (mk.popup) marker.bindPopup(mk.popup);
|
|
168
|
+
marker.addTo(map);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
(block.circles || []).forEach((c) => {
|
|
172
|
+
const circle = L.circle([c.lat, c.lng], {
|
|
173
|
+
radius: c.radius,
|
|
174
|
+
color: c.color || "#0077CC",
|
|
175
|
+
fillColor: c.fillColor || c.color || "#0077CC",
|
|
176
|
+
fillOpacity: c.fillOpacity != null ? c.fillOpacity : 0.2,
|
|
177
|
+
});
|
|
178
|
+
if (c.popup) circle.bindPopup(c.popup);
|
|
179
|
+
circle.addTo(map);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
(block.polylines || []).forEach((pl) => {
|
|
183
|
+
const line = L.polyline(pl.points, {
|
|
184
|
+
color: pl.color || "#DD0A73",
|
|
185
|
+
weight: pl.weight != null ? pl.weight : 2,
|
|
186
|
+
opacity: pl.opacity != null ? pl.opacity : 0.8,
|
|
187
|
+
});
|
|
188
|
+
if (pl.popup) line.bindPopup(pl.popup);
|
|
189
|
+
line.addTo(map);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
(block.polygons || []).forEach((pg) => {
|
|
193
|
+
const poly = L.polygon(pg.points, {
|
|
194
|
+
color: pg.color || "#017D73",
|
|
195
|
+
fillColor: pg.fillColor || pg.color || "#017D73",
|
|
196
|
+
fillOpacity: pg.fillOpacity != null ? pg.fillOpacity : 0.3,
|
|
197
|
+
});
|
|
198
|
+
if (pg.popup) poly.bindPopup(pg.popup);
|
|
199
|
+
poly.addTo(map);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Choropleth: fetch geojson_url directly (no same-origin proxy in the
|
|
203
|
+
// iframe), join external data by key, shade by value. Best-effort \u2014 the
|
|
204
|
+
// host CSP must allow the geojson host in connectDomains.
|
|
205
|
+
if (block.geojson_url) {
|
|
206
|
+
const choropleth = block.choropleth || null;
|
|
207
|
+
const dataJoin = block.data_join || null;
|
|
208
|
+
const colorScale = (choropleth && choropleth.scale) || ["#fee5d9", "#fcae91", "#fb6a4a", "#de2d26", "#a50f15"];
|
|
209
|
+
const steps = (choropleth && choropleth.steps) || [];
|
|
210
|
+
const fillOpacity = choropleth && choropleth.opacity != null ? choropleth.opacity : 0.7;
|
|
211
|
+
|
|
212
|
+
const colorForValue = (value) => {
|
|
213
|
+
if (value == null || !steps.length) return "#cccccc";
|
|
214
|
+
let bucket = steps.findIndex((threshold) => value < threshold);
|
|
215
|
+
if (bucket === -1) bucket = colorScale.length - 1;
|
|
216
|
+
return colorScale[Math.min(bucket, colorScale.length - 1)];
|
|
217
|
+
};
|
|
218
|
+
const lookupJoined = (feature) => {
|
|
219
|
+
if (!dataJoin) return undefined;
|
|
220
|
+
const key = feature && feature.properties ? feature.properties[dataJoin.join_key] : undefined;
|
|
221
|
+
return key != null && dataJoin.data ? dataJoin.data[String(key)] : undefined;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
fetch(block.geojson_url)
|
|
225
|
+
.then((response) => {
|
|
226
|
+
if (!response.ok) throw new Error("GeoJSON HTTP " + response.status);
|
|
227
|
+
return response.json();
|
|
228
|
+
})
|
|
229
|
+
.then((geojson) => {
|
|
230
|
+
if (!map) return;
|
|
231
|
+
let featureCollection = Array.isArray(geojson)
|
|
232
|
+
? { type: "FeatureCollection", features: geojson }
|
|
233
|
+
: geojson;
|
|
234
|
+
const features = Array.isArray(featureCollection && featureCollection.features)
|
|
235
|
+
? featureCollection.features
|
|
236
|
+
: [];
|
|
237
|
+
if (!features.filter((f) => f && f.geometry).length) {
|
|
238
|
+
showStatus("\u26A0\uFE0F Choropl\xE8the: le GeoJSON ne contient aucune g\xE9om\xE9trie exploitable.", true);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const layer = L.geoJSON(featureCollection, {
|
|
242
|
+
style: (feature) => {
|
|
243
|
+
const joined = lookupJoined(feature);
|
|
244
|
+
const value = joined && choropleth ? joined[choropleth.property] : undefined;
|
|
245
|
+
return { color: "#ffffff", weight: 1, fillColor: colorForValue(value), fillOpacity };
|
|
246
|
+
},
|
|
247
|
+
onEachFeature: (feature, featureLayer) => {
|
|
248
|
+
const joined = lookupJoined(feature);
|
|
249
|
+
if (!joined) return;
|
|
250
|
+
const rows = Object.keys(joined)
|
|
251
|
+
.map((k) => "<div><strong>" + k + ":</strong> " + joined[k] + "</div>")
|
|
252
|
+
.join("");
|
|
253
|
+
featureLayer.bindPopup('<div style="min-width:160px">' + rows + "</div>");
|
|
254
|
+
},
|
|
255
|
+
}).addTo(map);
|
|
256
|
+
try {
|
|
257
|
+
const bounds = layer.getBounds();
|
|
258
|
+
if (bounds.isValid()) map.fitBounds(bounds, { padding: [20, 20] });
|
|
259
|
+
} catch (boundsError) { /* keep configured center/zoom */ }
|
|
260
|
+
})
|
|
261
|
+
.catch((geoError) => {
|
|
262
|
+
showStatus("\u26A0\uFE0F Choropl\xE8the: " + (geoError && geoError.message ? geoError.message : String(geoError)), true);
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Tiles are laid out from the container size; nudge leaflet to remeasure
|
|
267
|
+
// now that the node is attached (Slack iframes size lazily).
|
|
268
|
+
setTimeout(() => { try { map.invalidateSize(); } catch (resizeError) {} }, 0);
|
|
269
|
+
} catch (mapError) {
|
|
270
|
+
mapNode.textContent = "Map render error: " + mapError.message;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function renderBlock(block) {
|
|
275
|
+
const container = el("div", "stkxp-block");
|
|
276
|
+
const blockType = block && block.type;
|
|
277
|
+
|
|
278
|
+
if (blockType === "markdown" || blockType === "markdown_token" || blockType === "text") {
|
|
279
|
+
// "text" covers LLM content-block arrays ({index,type:"text",text}); the
|
|
280
|
+
// text is markdown (may contain tables), so render it as such.
|
|
281
|
+
renderTitleAndDesc(container, block);
|
|
282
|
+
renderMarkdown(container, block.body != null ? block.body : block.text);
|
|
283
|
+
} else if (blockType === "echarts") {
|
|
284
|
+
renderTitleAndDesc(container, block);
|
|
285
|
+
const chartNode = el("div", "stkxp-chart");
|
|
286
|
+
container.appendChild(chartNode);
|
|
287
|
+
// ECharts needs the node in the DOM with a measurable width before init.
|
|
288
|
+
root.appendChild(container);
|
|
289
|
+
try {
|
|
290
|
+
const chart = echarts.init(chartNode);
|
|
291
|
+
chart.setOption(block.options || {});
|
|
292
|
+
window.addEventListener("resize", () => chart.resize());
|
|
293
|
+
} catch (chartError) {
|
|
294
|
+
chartNode.textContent = "Chart render error: " + chartError.message;
|
|
295
|
+
}
|
|
296
|
+
return; // already appended
|
|
297
|
+
} else if (blockType === "mermaid") {
|
|
298
|
+
renderTitleAndDesc(container, block);
|
|
299
|
+
const diagramNode = el("div", "stkxp-mermaid");
|
|
300
|
+
container.appendChild(diagramNode);
|
|
301
|
+
try {
|
|
302
|
+
const { svg } = await mermaid.render("stkxp-mermaid-" + (mermaidSeq++), String(block.body || ""));
|
|
303
|
+
diagramNode.innerHTML = svg;
|
|
304
|
+
} catch (diagramError) {
|
|
305
|
+
diagramNode.textContent = "Diagram render error: " + diagramError.message;
|
|
306
|
+
}
|
|
307
|
+
} else if (blockType === "table") {
|
|
308
|
+
renderTitleAndDesc(container, block);
|
|
309
|
+
container.appendChild(buildTable(block));
|
|
310
|
+
} else if (blockType === "leaflet") {
|
|
311
|
+
renderTitleAndDesc(container, block);
|
|
312
|
+
renderLeaflet(container, block);
|
|
313
|
+
return; // already appended
|
|
314
|
+
} else {
|
|
315
|
+
// raw / eui / recharts / unknown \u2192 readable JSON fallback.
|
|
316
|
+
renderTitleAndDesc(container, block);
|
|
317
|
+
const pre = el("pre", "stkxp-raw");
|
|
318
|
+
pre.textContent = JSON.stringify(block, null, 2);
|
|
319
|
+
container.appendChild(pre);
|
|
320
|
+
}
|
|
321
|
+
root.appendChild(container);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function formatCell(value) {
|
|
325
|
+
if (value === null || value === undefined) return "";
|
|
326
|
+
return typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function buildTable(block) {
|
|
330
|
+
const rows = Array.isArray(block.data) ? block.data : (Array.isArray(block.rows) ? block.rows : []);
|
|
331
|
+
const table = el("table", "stkxp-table");
|
|
332
|
+
|
|
333
|
+
// Columns may be: an array of strings, an array of objects, or absent.
|
|
334
|
+
// Rows may be: positional arrays, or keyed objects. Normalise both so a
|
|
335
|
+
// cell is looked up by array index (for string columns / array rows) OR by
|
|
336
|
+
// object key (for object columns / object rows) \u2014 matching the app's native
|
|
337
|
+
// table renderer.
|
|
338
|
+
let normCols = [];
|
|
339
|
+
if (Array.isArray(block.columns) && block.columns.length > 0) {
|
|
340
|
+
normCols = block.columns.map((col, i) => {
|
|
341
|
+
if (typeof col === "string") return { label: col, key: col, index: i };
|
|
342
|
+
return {
|
|
343
|
+
label: col.name || col.headerName || col.label || col.field || col.key || "",
|
|
344
|
+
key: col.field || col.key || col.name,
|
|
345
|
+
index: i,
|
|
346
|
+
};
|
|
347
|
+
});
|
|
348
|
+
} else if (rows.length > 0 && rows[0] && typeof rows[0] === "object" && !Array.isArray(rows[0])) {
|
|
349
|
+
normCols = Object.keys(rows[0]).map((k, i) => ({ label: k, key: k, index: i }));
|
|
350
|
+
} else if (rows.length > 0 && Array.isArray(rows[0])) {
|
|
351
|
+
normCols = rows[0].map((_, i) => ({ label: "Col " + (i + 1), key: null, index: i }));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const thead = el("thead");
|
|
355
|
+
const headRow = el("tr");
|
|
356
|
+
for (const col of normCols) {
|
|
357
|
+
const th = el("th");
|
|
358
|
+
th.textContent = col.label;
|
|
359
|
+
headRow.appendChild(th);
|
|
360
|
+
}
|
|
361
|
+
thead.appendChild(headRow);
|
|
362
|
+
table.appendChild(thead);
|
|
363
|
+
|
|
364
|
+
const tbody = el("tbody");
|
|
365
|
+
for (const row of rows) {
|
|
366
|
+
const tr = el("tr");
|
|
367
|
+
for (const col of normCols) {
|
|
368
|
+
const td = el("td");
|
|
369
|
+
const cell = Array.isArray(row)
|
|
370
|
+
? row[col.index]
|
|
371
|
+
: (row && col.key != null ? row[col.key] : undefined);
|
|
372
|
+
td.textContent = formatCell(cell);
|
|
373
|
+
tr.appendChild(td);
|
|
374
|
+
}
|
|
375
|
+
tbody.appendChild(tr);
|
|
376
|
+
}
|
|
377
|
+
table.appendChild(tbody);
|
|
378
|
+
return table;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
async function render(result) {
|
|
382
|
+
const status = result && result.status;
|
|
383
|
+
const blocks = Array.isArray(result && result.blocks) ? result.blocks : [];
|
|
384
|
+
const hasContent = !!((result && result.text && result.text.trim()) || blocks.length > 0);
|
|
385
|
+
|
|
386
|
+
// Running with nothing yet \u2192 full-screen spinner + elapsed counter.
|
|
387
|
+
if (status === "running" && !hasContent) {
|
|
388
|
+
renderLoading(result);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Content path: terminal result, OR a still-running run with partial output
|
|
393
|
+
// (Option A progressive rendering). Clear and rebuild; the loading counter
|
|
394
|
+
// is no longer shown, so stop the elapsed ticker from touching a dead node.
|
|
395
|
+
root.innerHTML = "";
|
|
396
|
+
elapsedNode = null;
|
|
397
|
+
if (status !== "running") runStartMs = null;
|
|
398
|
+
|
|
399
|
+
if (status === "error") {
|
|
400
|
+
const statusNode = el("div", "stkxp-status error");
|
|
401
|
+
statusNode.textContent = "Team run failed: " + (result.error || "unknown error");
|
|
402
|
+
root.appendChild(statusNode);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (result && result.text) {
|
|
407
|
+
renderMarkdown(root, result.text);
|
|
408
|
+
}
|
|
409
|
+
for (const block of blocks) {
|
|
410
|
+
await renderBlock(block);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (status === "running") {
|
|
414
|
+
// Partial output shown; more sections still arriving \u2192 inline spinner.
|
|
415
|
+
const footer = el("div", "stkxp-loading");
|
|
416
|
+
footer.appendChild(el("div", "stkxp-spinner"));
|
|
417
|
+
const footerText = el("div", "stkxp-loading-text");
|
|
418
|
+
footerText.textContent = "Still running\u2026 more sections may appear";
|
|
419
|
+
footer.appendChild(footerText);
|
|
420
|
+
root.appendChild(footer);
|
|
421
|
+
} else if (!hasContent) {
|
|
422
|
+
const emptyNode = el("div", "stkxp-status");
|
|
423
|
+
emptyNode.textContent = "Team run completed with no content.";
|
|
424
|
+
root.appendChild(emptyNode);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
429
|
+
const POLL_INTERVAL_MS = 1500; // snappy enough for progressive block updates
|
|
430
|
+
const POLL_MAX_MS = 6 * 60 * 1000; // give up after 6 minutes
|
|
431
|
+
let polling = false;
|
|
432
|
+
let lastSig = ""; // content signature, to re-render only when partial output changes
|
|
433
|
+
|
|
434
|
+
function contentSig(result) {
|
|
435
|
+
const blocks = Array.isArray(result && result.blocks) ? result.blocks : [];
|
|
436
|
+
const textLen = result && typeof result.text === "string" ? result.text.length : 0;
|
|
437
|
+
return textLen + "|" + blocks.length + "|" + blocks.map((b) => b && b.type).join(",");
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const app = new App({ name: "Stack Expert Team", version: "1.0.0" });
|
|
441
|
+
|
|
442
|
+
// Team runs take minutes, so the ask_ tool usually returns status "running"
|
|
443
|
+
// with a runId. Rather than block the tool call, we self-poll get_team_run
|
|
444
|
+
// over the MCP Apps runtime (app.callServerTool) and re-render when it
|
|
445
|
+
// completes \u2014 the card updates live inside Slack.
|
|
446
|
+
async function pollUntilDone(runId) {
|
|
447
|
+
const startedAt = Date.now();
|
|
448
|
+
while (Date.now() - startedAt < POLL_MAX_MS) {
|
|
449
|
+
await sleep(POLL_INTERVAL_MS);
|
|
450
|
+
try {
|
|
451
|
+
const toolResult = await app.callServerTool({
|
|
452
|
+
name: "get_team_run",
|
|
453
|
+
arguments: { runId },
|
|
454
|
+
});
|
|
455
|
+
const polled = toolResult && toolResult.structuredContent;
|
|
456
|
+
if (!polled) continue;
|
|
457
|
+
if (polled.status && polled.status !== "running") {
|
|
458
|
+
await render(polled);
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
// Still running: re-render only when the partial content changed (a new
|
|
462
|
+
// block/section landed), so the view fills in progressively without
|
|
463
|
+
// thrashing. The full-spinner elapsed counter keeps ticking otherwise.
|
|
464
|
+
const sig = contentSig(polled);
|
|
465
|
+
if (sig !== lastSig) {
|
|
466
|
+
lastSig = sig;
|
|
467
|
+
await render(polled);
|
|
468
|
+
}
|
|
469
|
+
} catch (pollError) {
|
|
470
|
+
console.error("[stkxp-ui] poll error", pollError);
|
|
471
|
+
showStatus(
|
|
472
|
+
"\u274C Ce client ne rafra\xEEchit pas la carte automatiquement : " +
|
|
473
|
+
(pollError && pollError.message ? pollError.message : String(pollError)),
|
|
474
|
+
true
|
|
475
|
+
);
|
|
476
|
+
return; // host may not allow tool calls \u2014 stop quietly
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
let launched = false;
|
|
482
|
+
|
|
483
|
+
// ask_ now returns { runToken, message, context } with no run started. The
|
|
484
|
+
// card launches the run itself (start_team_run), guarded so the N iframe
|
|
485
|
+
// mounts MCPJam creates do not each fire a launch, then polls to completion.
|
|
486
|
+
async function launchAndPoll(input) {
|
|
487
|
+
if (launched) return;
|
|
488
|
+
launched = true;
|
|
489
|
+
renderLoading({ status: "running" });
|
|
490
|
+
const ticker = setInterval(updateElapsed, 1000);
|
|
491
|
+
try {
|
|
492
|
+
const startResult = await app.callServerTool({
|
|
493
|
+
name: "start_team_run",
|
|
494
|
+
arguments: { runToken: input.runToken, message: input.message, context: input.context },
|
|
495
|
+
});
|
|
496
|
+
const started = startResult && startResult.structuredContent;
|
|
497
|
+
if (!started || !started.runId) {
|
|
498
|
+
showStatus("\u274C D\xE9marrage du run impossible (r\xE9ponse inattendue).", true);
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
if (started.status && started.status !== "running") {
|
|
502
|
+
await render(started);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
lastSig = contentSig(started);
|
|
506
|
+
await pollUntilDone(started.runId);
|
|
507
|
+
} catch (startError) {
|
|
508
|
+
console.error("[stkxp-ui] start error", startError);
|
|
509
|
+
showStatus(
|
|
510
|
+
"\u274C Ce client ne permet pas de lancer le run depuis la carte : " +
|
|
511
|
+
(startError && startError.message ? startError.message : String(startError)),
|
|
512
|
+
true
|
|
513
|
+
);
|
|
514
|
+
} finally {
|
|
515
|
+
clearInterval(ticker);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
async function handleResult(result) {
|
|
520
|
+
// New flow: ask_ hands us a runToken (no run yet) \u2192 launch + poll.
|
|
521
|
+
if (result && result.runToken && !result.runId) {
|
|
522
|
+
await launchAndPoll(result);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
// Legacy/get_run flow: a RunResult with runId.
|
|
526
|
+
lastSig = contentSig(result);
|
|
527
|
+
await render(result);
|
|
528
|
+
if (result && result.status === "running" && result.runId && !polling) {
|
|
529
|
+
polling = true;
|
|
530
|
+
const ticker = setInterval(updateElapsed, 1000);
|
|
531
|
+
try {
|
|
532
|
+
await pollUntilDone(result.runId);
|
|
533
|
+
} finally {
|
|
534
|
+
clearInterval(ticker);
|
|
535
|
+
polling = false;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
app.ontoolresult = (params) => {
|
|
541
|
+
try {
|
|
542
|
+
if (params && params.structuredContent) handleResult(params.structuredContent);
|
|
543
|
+
} catch (renderError) {
|
|
544
|
+
console.error("[stkxp-ui] render error", renderError);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
app.onerror = (runtimeError) => console.error("[stkxp-ui] runtime error", runtimeError);
|
|
548
|
+
await app.connect();
|
|
549
|
+
</script>
|
|
550
|
+
</body>
|
|
551
|
+
</html>`;function l(o){o.registerResource("Stack Expert team run",e,{title:"Team run",description:"Interactive view of a Stack Expert team run (charts, diagrams, tables).",mimeType:t},async()=>({contents:[{uri:e,mimeType:t,text:a,_meta:{ui:{csp:n}}}]}))}const s={ui:{resourceUri:e}};export{n as TEAM_UI_CSP,a as TEAM_UI_HTML,t as TEAM_UI_MIME_TYPE,e as TEAM_UI_RESOURCE_URI,s as TEAM_UI_TOOL_META,l as registerTeamUiResource};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const s=9e5,n=new Map;function o(e){for(const[t,r]of n)e-r.updatedAt>9e5&&n.delete(t)}function i(e,t){if(!e)return;const r=Date.now();n.set(e,{text:t.text,blocks:t.blocks,updatedAt:r}),n.size>100&&o(r)}function u(e){if(!e)return;const t=n.get(e);if(t){if(Date.now()-t.updatedAt>9e5){n.delete(e);return}return t}}function d(e){e&&n.delete(e)}export{d as clearRunProgress,u as getRunProgress,i as setRunProgress};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{HumanMessage as ae,AIMessage as we}from"@langchain/core/messages";import{MemorySaver as Te}from"@langchain/langgraph-checkpoint";import{randomUUID as re}from"crypto";import{Client as ke}from"@elastic/elasticsearch";import{config as Ae}from"../config";import{buildAppFromDefinition as oe}from"../graph/graph-builder";import{buildKibanaAgentApp as be}from"../graph/kibana-agent-executor";import{buildA2aAgentApp as Ie}from"../graph/a2a-agent-executor";import{adaptDelegatedAgentApp as $e}from"../graph/delegated-agent-adapter";import{getGraph as ie}from"./graph-registry-service";import{resolveAssistants as Se}from"./assistant-resolver";import{getUserProviders as _e}from"../../services/auth";import{getTeamWebhookConfig as Ce,getTeamSharedContext as Re}from"./teams-service";import{updateChat as ve,getChatById as xe}from"./chats-service";import{completeChatRun as Me,updateChatRun as Ne,classifyError as De}from"./chat-runs-service";import{updateWebhookCall as Ee}from"./webhook-calls-service";import{publishReply as He}from"./asyncapi-reply-service";import{createShareLink as Pe,updateRunShareSnapshot as Oe,buildRunShareUrl as Be}from"./share-service";import{RunAnalyticsCollector as Le}from"./run-analytics-collector";import{getTrigger as le}from"./trigger-service";import{setRunProgress as Ue,getRunProgress as je,clearRunProgress as Fe}from"./team-run-progress";import{extractTextAndBlocks as Je}from"./team-mcp-result";import{AsyncApiSink as ce}from"./asyncapi-sink";import{TraceBusSink as Ve}from"../../services/trace-bus-sink";import{extractTextFromStreamChunk as We,fanout as v}from"./run-stream-sink";import{getPlatformById as Xe}from"./platforms-service";import{registerActiveRunMeta as Ge,unregisterActiveRunMeta as Ke}from"../runtime/active-runs-registry";import{publishTraceEvent as J}from"../runtime/trace-bus";const qe=new ke(Ae.elasticsearch),Ye=".stkxp_teams";function ze(l){let s;try{s=JSON.stringify(l,null,2)}catch{s="<unserialisable payload>"}return["[Event webhook]","Source: webhook","Payload:","```json",s,"```"].join(`
|
|
2
|
+
`)}function V(l){const s=l.trim().split(/\r?\n/).filter(n=>!/^```[a-z]*\s*$/i.test(n.trim())).join(`
|
|
3
|
+
`).trim();if(!s||s[0]!=="{"&&s[0]!=="[")return null;try{const n=JSON.parse(s);if(Array.isArray(n))return n.every(c=>c&&typeof c=="object"&&typeof c.type=="string")&&n.length>0?n:null;if(n&&typeof n=="object"&&typeof n.type=="string")return[n]}catch{}if(s[0]!=="{")return null;const e=s.split(/\n+/).map(n=>n.trim()).filter(Boolean);if(e.length===0)return null;const t=[];for(let n=0;n<e.length;n++){const i=e[n];try{const c=JSON.parse(i);if(!c||typeof c!="object"||Array.isArray(c)||typeof c.type!="string")return null;t.push(c)}catch{if(n===e.length-1&&t.length>0)break;return null}}return t.length>0?t:null}function ue(l){const s=[];for(const e of l||[]){const t=e?._getType?.()??e?.constructor?.name?.toLowerCase()??"";if(t==="tool"||t==="toolmessage"||t==="system"||t==="systemmessage")continue;const n=t==="human"||t==="humanmessage"?"user":"assistant";let i=e?.content??"";if(Array.isArray(i)){const c=[];for(const g of i)typeof g=="string"?c.push(g):g&&typeof g=="object"&&typeof g.text=="string"&&c.push(g.text);i=c.join("")}if(!(!i||typeof i=="string"&&i.trim()==="")){if(n==="assistant"&&typeof i=="string"){const c=V(i);c&&(i=JSON.stringify(c))}s.push({role:n,content:i,timestamp:new Date().toISOString(),id:e?.id||re(),assistantId:e?.additional_kwargs?.assistant_id,assistantName:e?.additional_kwargs?.assistant_name})}}return s}function Qe(l){const e=(l?.teamAssistantResults||[]).filter(n=>n&&n.success!==!1&&n.output!=null),t=[];for(const n of e){let i=typeof n.output=="string"?n.output:String(n.output??"");if(!i.trim())continue;const c=V(i);c&&(i=JSON.stringify(c)),t.push({role:"assistant",content:i,timestamp:new Date().toISOString(),id:re(),assistantId:n.assistantId,assistantName:n.assistantName})}return t}const Ze=process.env.ASYNCAPI_REPLY_FALLBACK_PLAIN_TEXT!=="false";function et(l){const s=l?.messages||[];for(let e=s.length-1;e>=0;e--){const t=s[e],n=t?._getType?.()??t?.constructor?.name?.toLowerCase()??"";if(n!=="ai"&&n!=="aimessage")continue;let i=t?.content??"";if(Array.isArray(i)){const g=[];for(const h of i)typeof h=="string"?g.push(h):h&&typeof h=="object"&&typeof h.text=="string"&&g.push(h.text);i=g.join("")}if(typeof i!="string"||!i.trim())continue;const c=V(i);return c||(Ze?(console.log(`[TeamRunnerHeadless] reply blocks fallback: team responded with non-NDJSON content (${i.length} chars), wrapping in a markdown block`),[{type:"markdown",body:i}]):void 0)}}function tt(l){return(l?.teamAssistantResults||[]).map(e=>({assistantId:e.assistantId,assistantName:e.assistantName,toolCallsCount:Array.isArray(e.toolsUsed)?e.toolsUsed.length:0,llmCallsCount:0,success:!!e.success}))}function nt(l){const s=l?.teamAssistantResults||[],e=new Set;for(const t of s)for(const n of t.toolsUsed||[])typeof n=="string"?e.add(n):n?.name&&e.add(n.name);return Array.from(e)}async function st(l){try{const e=(await qe.get({index:Ye,id:l}))._source??{};return{id:l,name:e.name,owner:e.owner,graphId:e.graphId,assistantIds:Array.isArray(e.assistantIds)?e.assistantIds:[],assistants:Array.isArray(e.assistants)?e.assistants:[]}}catch(s){if(s?.meta?.statusCode===404)return null;throw s}}function at(l,s,e){const t=l.graphType==="kibana_agent"?be(l):Ie(l);return $e(t,s,e)}function rt(l,s){const e=new Map;for(const t of s??[])t?.id&&e.set(t.id,t);return l.map(t=>{const n=e.get(t.assistantId);return{...t,condition:n?.condition??null,runAlways:n?.runAlways??!1}})}const ot=parseInt(process.env.MAX_WEBHOOK_DEPTH??"5",10);async function Ot(l){const{teamId:s,runId:e,chatId:t,webhookCallId:n,payload:i,signal:c,triggerId:g,threadIdOverride:h,conversationId:D,extraSinks:P}=l,W=l.channel??"api",de=h&&h.trim()!==""?h:t,_=l.depth??0,X=l.maxDepth??ot,O=Date.now();let S=!1,m=null,G=!1,B,b=null,C=null,T=null,w;try{if(_>=X)throw Object.assign(new Error(`Webhook chain depth ${_} reached max ${X} \u2014 possible feedback loop, aborting`),{errorType:"recursion_guard"});const r=await st(s);if(!r)throw new Error(`Team ${s} not found at runner start`);if(!r.owner)throw new Error(`Team ${s} has no owner`);if(!r.graphId)throw new Error(`Team ${s} has no graphId \u2014 webhook runs require a coordination graph (see project_webhook_team_runs)`);if(!r.assistantIds||r.assistantIds.length===0)throw new Error(`Team ${s} has no assistants`);const x=await Se(r.assistantIds,r.owner);if(x.length===0)throw new Error(`No assistants resolved for team ${s} (requested: ${r.assistantIds.join(", ")})`);const d=rt(x,r.assistants),me=d.filter(a=>a.condition).length;console.log(`[TeamRunnerHeadless] Merged routing config onto ${d.length} assistant(s) for team ${s} (${me} with a JSONata condition)`);const I=await ie(r.graphId);if(!I||I.enabled===!1)throw new Error(`Team graph ${r.graphId} not found or disabled`);if(!(I.nodes||[]).some(a=>a.type==="team_pipeline"||a.type==="team_parallel"||a.type==="team_decider"||a.type==="team_router"))throw new Error(`Graph ${r.graphId} is not a team coordination graph \u2014 webhook runs require a graph with at least one team_* node`);const ge=(I.nodes||[]).some(a=>a.type==="team_decider"),K=await _e(r.owner).catch(a=>(console.warn(`[TeamRunnerHeadless] getUserProviders failed for ${r.owner}: ${a?.message} \u2014 falling back to env-provided keys`),null)),L=(await Re(s).catch(()=>null))?.context||void 0,M=`${r.name||"Team"} \u2014 webhook run`;let E,U;try{const a=await Pe({type:"run",chatId:t,chatTitle:M,chatSnapshot:{title:M,teamName:r.name||"",messages:[],capturedAt:new Date().toISOString()},ownerId:r.owner,label:`${M} #${e}`,allowedEmails:[],allowedDomains:[]});E=a.id,U=Be(a.id),console.log(`[TeamRunnerHeadless] Pre-created run share link ${a.id} for chat ${t}`)}catch(a){console.warn(`[TeamRunnerHeadless] Failed to pre-create run share link for chat ${t}: ${a?.message} \u2014 assistants will have no share URL to embed`)}const q=U?`${L?`${L}
|
|
4
|
+
|
|
5
|
+
`:""}[Chat share link]
|
|
6
|
+
Use this EXACT URL when sharing or linking to this conversation (e.g. in a Slack message). Do NOT invent, modify, or shorten it:
|
|
7
|
+
${U}`:L,Y=new Te,j=ze(i),pe=new ae({content:j});let N=[];if(h)try{const p=(await xe(t,r.owner))?.messages??[];for(const f of p){const o=typeof f.content=="string"?f.content:JSON.stringify(f.content??"");o.trim()&&(f.role==="user"?N.push(new ae({content:o})):(f.role==="assistant"||f.role==="agent")&&N.push(new we({content:o})))}N.length>0&&console.log(`[TeamRunnerHeadless] V2.3 multi-turn: rehydrated ${N.length} prior message(s) for chat ${t} (conversationId=${D??"(unset)"})`)}catch(a){console.warn(`[TeamRunnerHeadless] V2.3 history rehydration failed for chat ${t}: ${a?.message} \u2014 proceeding with empty history`)}const fe=async(a,p)=>{const f=`${t}-ta-${p}`,o=a.graphId;if(!o)throw new Error(`Sub-assistant "${a.name}" has no graphId \u2014 cannot build sub-graph`);const u=await ie(o);if(!u||u.enabled===!1)throw new Error(`Sub-assistant graph ${o} not found or disabled (assistant: ${a.name})`);return u.graphType==="kibana_agent"||u.graphType==="a2a_agent"?at(u,f,a.name):await oe(u,{mcp:void 0,memory:Y,threadId:f,userProviders:K,username:r.owner,teamId:s,chatId:t,rawUserInput:j,userContext:q,behindDecider:ge,webhookDepth:_,channel:W,assistant:{...a,overrideAllowedTools:a?.tools},mcpServersPolicy:a?.mcp_servers_policy})},he=await oe(I,{mcp:void 0,memory:Y,threadId:t,userProviders:K,username:r.owner,teamId:s,chatId:t,rawUserInput:j,userContext:q,teamAssistants:d,buildAssistantApp:fe,webhookDepth:_,channel:W,assistant:{name:r.name||`team-${s}`,teamAssistants:d}});console.log(`[TeamRunnerHeadless] Invoking team ${s} graph (assistants=${d.length}, runId=${e})`),Ge({runId:e,startTime:O,username:r.owner,chatId:t,teamId:s,teamName:r.name,assistantName:`team:${r.name||s}`,currentNode:I.name||r.graphId}),G=!0,J(e,{kind:"node_start",ts:Date.now(),node:I.name||r.graphId||"team_graph"});const z=new Map;d.forEach((a,p)=>{z.set(`${t}-ta-${p}`,{assistantId:a.assistantId,assistantName:a.name})});const Q=d.length===1,Z=d[0],ee=Q?Z.assistantId:`team-${s}`,te=Q?Z.name:r.name||`team-${s}`;b=new Le({resolveAssistant:a=>z.get(a),defaultAssistant:{assistantId:ee,assistantName:te}}),C={runId:e,chatId:t,username:r.owner,teamId:s,assistantId:ee,assistantName:te};let $;if(g&&(w=await le(g).catch(()=>null),(w?ce.validate(w):{ok:!1,reason:"no_trigger"}).ok&&n&&w)){const p=w.inputTemplate?.asyncapi?.platformId,o=(p?await Xe(p,w.owner,!1,!0).catch(()=>null):null)?.config?.broker;if(o?.host&&o?.protocol){const u=new ce({trigger:w,broker:o,incomingDepth:_,webhookCallId:n}),y=new Ve;T=[u,y],console.log(`[TeamRunnerHeadless] V2.5 streaming enabled for run ${e} (trigger=${w.id}, batchMs=${w.streamingBatchMs??50}, sinks=[AsyncApiSink,TraceBusSink])`)}}P&&P.length>0&&(T=[...T||[],...P]),T&&await v(T,"runStart",{runId:e,owner:r.owner,conversationId:D});{const a=await he.streamEvents({messages:[...N,pe]},{version:"v2",configurable:{thread_id:de,run_id:e},recursionLimit:100,signal:c}),p=T,f=new Map;$=null;for await(const o of a){if(c?.aborted){console.log(`[TeamRunnerHeadless] streaming aborted for run ${e}`);break}try{if(b?.onEvent(o),p){if(o.event==="on_chat_model_stream"){const u=We(o.data?.chunk);u&&await v(p,"onMarkdownToken",{text:u,assistantName:o.metadata?.assistantName??o.name??void 0,ts:Date.now()})}else if(o.event==="on_tool_start"){const u=String(o.name??"unknown_tool"),y=Date.now();f.set(`${u}:${o.run_id??""}`,y);const k=o.data?.input,A=typeof k=="string"?k:JSON.stringify(k??null).slice(0,2e3);await v(p,"onToolStart",{toolName:u,toolInput:A,ts:y})}else if(o.event==="on_tool_end"){const u=String(o.name??"unknown_tool"),y=`${u}:${o.run_id??""}`,k=f.get(y)??Date.now();f.delete(y);const A=o.data?.output,H=typeof A=="string"?A.slice(0,2e3):JSON.stringify(A??null).slice(0,2e3);await v(p,"onToolEnd",{toolName:u,toolResult:H,durationMs:Date.now()-k,ts:Date.now()})}}if(o.event==="on_chain_end"&&o.name==="LangGraph"&&($=o.data?.output??$),o.event==="on_chat_model_end")try{const u=o.data?.output;if(u){const y=ue([u]);if(y.length>0){const{text:k,blocks:A}=Je(y),H=!!(A&&A.length>0),F=je(e),ye=!!(F&&F.blocks&&F.blocks.length>0);(H||!ye)&&(H||k&&k.trim())&&Ue(e,{text:k,blocks:A??[]})}}}catch{}}catch(u){console.warn(`[TeamRunnerHeadless] stream event handler threw on ${o?.event}: ${u?.message??u}`)}}}J(e,{kind:"node_end",ts:Date.now(),node:I.name||r.graphId||"team_graph",durationMs:Date.now()-O});let R=ue($?.messages||[]);if(!R.some(a=>a.role==="assistant")){const a=Qe($);a.length>0&&(R=[...R,...a])}const ne=tt($);B=et($),await ve(t,r.owner,{messages:R,assistants:ne}).catch(a=>{console.error(`[TeamRunnerHeadless] Failed to persist chat ${t}:`,a?.message)}),E&&await Oe(E,r.owner,{title:M,teamName:r.name||"",messages:R,capturedAt:new Date().toISOString()},M).catch(a=>console.warn(`[TeamRunnerHeadless] Failed to backfill share snapshot ${E}: ${a?.message}`));const se=b?.getUniqueToolNames()??[];await Ne(e,{toolsUsed:se.length>0?se:nt($),toolCallsCount:b?.getToolCallsCount()??ne.reduce((a,p)=>a+p.toolCallsCount,0),messageCount:R.length}),S=!0}catch(r){m=De(r),console.error(`[TeamRunnerHeadless] Run ${e} failed (${m.errorType}):`,m.errorMessage)}finally{const r=Date.now()-O;G&&(S||J(e,{kind:"node_end",ts:Date.now(),node:"team_graph",durationMs:r}),Ke(e));const x=b?.getLlmUsage()??[];if(b&&C&&b.hasData()&&await b.persist(C).catch(d=>console.error(`[TeamRunnerHeadless] Failed to persist run analytics for ${e}: ${d?.message}`)),await Me(e,S?"success":"error",{...C?.assistantName?{assistantId:C.assistantId,assistantName:C.assistantName}:{},...x.length>0?{llmUsage:x}:{},...m?{errorType:m.errorType,errorMessage:m.errorMessage}:{}}).catch(d=>{console.error(`[TeamRunnerHeadless] Failed to complete chat run ${e}:`,d?.message)}),Fe(e),n&&await Ee(n,{status:S?"completed":"failed",durationMs:r,...m?{error:m.errorMessage}:{}}),T)try{await v(T,"flush",void 0),await v(T,"runEnd",{success:S,durationMs:r,blocks:B,...m?.errorType?{errorType:m.errorType}:{},...m?.errorMessage?{errorMessage:m.errorMessage}:{}})}catch(d){console.error(`[TeamRunnerHeadless] V2.5 stream sink finalisation threw for run ${e}:`,d?.message)}else if(g&&n)try{const d=w??await le(g);d?.replyChannel&&await He({trigger:d,webhookCallId:n,incomingDepth:_,runResult:{runId:e,status:S?"success":"error",durationMs:r,blocks:B,...D?{conversationId:D}:{},...m?.errorType?{errorType:m.errorType}:{},...m?.errorMessage?{errorMessage:m.errorMessage}:{}}})}catch(d){console.error(`[TeamRunnerHeadless] publishReply unexpectedly threw for run ${e}:`,d?.message)}console.log(`[TeamRunnerHeadless] Run ${e} finished in ${r}ms (success=${S})`)}}export{Ce as getTeamWebhookConfig,rt as mergeAssistantRouting,Ot as runTeamHeadless,V as tryParseNdjsonBlocks};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Client as a}from"@elastic/elasticsearch";import{config as o}from"../config";const c=new a(o.elasticsearch),i=".stkxp_teams";async function u(e){if(!e.owner||!e.query)return[];const n=[{term:{owner:e.owner}}],s=[];e.excludeTeamId&&s.push({term:{_id:e.excludeTeamId}});try{return((await c.search({index:i,body:{size:e.k??5,retriever:{rrf:{retrievers:[{standard:{query:{bool:{must:[{semantic:{field:"search_semantic",query:e.query}}],filter:n,must_not:s}}}},{standard:{query:{bool:{must:[{multi_match:{query:e.query,fields:["description","name"]}}],filter:n,must_not:s}}}}],rank_window_size:50,rank_constant:20}}}})).hits?.hits??[]).map(r=>({id:r._id,name:r._source?.name,description:r._source?.description,score:typeof r._score=="number"?r._score:void 0}))}catch(t){return console.error("[team-search] searchTeamsRRF failed:",t?.message??t),[]}}export{u as searchTeamsRRF};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{makeOwnerScopedClient as d}from"../../core/utils/owner-scope";const l=process.env.ELASTICSEARCH_HOST||"https://51.159.174.230:9205",g=process.env.ELASTICSEARCH_USER||"elastic",u=process.env.ELASTICSEARCH_PASSWORD||"",a=".stkxp_teams",o=d({node:l,auth:{username:g,password:u},tls:{rejectUnauthorized:!1},requestTimeout:6e4,maxRetries:3});async function h(t){try{const n=(await o.get({index:a,id:t}))._source;return{graphId:n?.graphId||void 0,name:n?.name}}catch(e){return e?.meta?.statusCode===404||console.error(`[Teams] Failed to fetch team ${t}:`,e?.message),null}}async function f(t){try{const n=(await o.get({index:a,id:t}))._source??{};return{name:n.name,owner:n.owner,assistantIds:Array.isArray(n.assistantIds)?n.assistantIds:[],assistants:Array.isArray(n.assistants)?n.assistants:[]}}catch(e){return e?.meta?.statusCode===404||console.error(`[Teams] Failed to fetch invocation config for team ${t}:`,e?.message),null}}async function w(t){try{const n=(await o.get({index:a,id:t}))._source,r=Array.isArray(n?.assistants)?n.assistants.map(s=>({id:s?.id,name:s?.name})):void 0;return{id:t,name:n?.name,owner:n?.owner,webhookToken:n?.webhookToken,webhookEnabled:n?.webhookEnabled,graphId:n?.graphId,assistants:r}}catch(e){return e?.meta?.statusCode===404||console.error(`[Teams] Failed to fetch webhook config for team ${t}:`,e?.message),null}}async function C(t){try{const n=(await o.get({index:a,id:t}))._source,r=Array.isArray(n?.assistants)?n.assistants.map(s=>({id:s?.id,name:s?.name,description:s?.description})):void 0;return{id:t,name:n?.name,owner:n?.owner,graphId:n?.graphId,mcpEnabled:n?.mcpEnabled,mcpSigningSecret:n?.mcpSigningSecret,mcpExposeAssistants:n?.mcpExposeAssistants,mcpAllowUnsigned:n?.mcpAllowUnsigned===!0,assistants:r}}catch(e){return e?.meta?.statusCode===404||console.error(`[Teams] Failed to fetch MCP config for team ${t}:`,e?.message),null}}async function x(t){try{const n=(await o.get({index:a,id:t}))._source;return n?.sharedContext?.context?{context:n.sharedContext.context,priority:n.sharedContext.priority==="after"?"after":"before",policy:n.sharedContext.policy||void 0}:null}catch(e){return e?.meta?.statusCode===404||console.error(`[Teams] Failed to fetch sharedContext for team ${t}:`,e?.message),null}}async function p(t,e){const n=await o.search({index:a,body:{query:{term:{owner:t}},size:1e3}}),r={};for(const s of n.hits.hits){const i=s._source,c=i?.channelCommands?.[e]?.commandIds??[];for(const m of c)r[m]={teamId:s._id,teamName:i?.name}}return r}async function A(t,e,n,r){const i=(await p(t,e))[n];return!i||i.teamId===r?null:i}async function b(t,e){try{const s=(await o.get({index:a,id:t}))._source?.channelCommands?.[e];return s?{commandIds:Array.isArray(s.commandIds)?s.commandIds:[],namespace:s.namespace,blockKitMode:s.blockKitMode===!0}:null}catch(n){return n?.meta?.statusCode===404||console.error(`[Teams] Failed to fetch channel commands for team ${t}/${e}:`,n?.message),null}}export{A as findTeamOwningCommand,p as getChannelCommandOwnership,h as getTeamById,b as getTeamChannelCommandConfig,f as getTeamInvocationConfig,C as getTeamMcpConfig,x as getTeamSharedContext,w as getTeamWebhookConfig};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{resolveNodeConfigs as x}from"./graph-registry-service";const y=".stkxp_llm_routing_rules",u=new Set(["system","tool","subgraph","check_reset","namespace_context","team_pipeline","team_parallel"]),p=(c,s)=>{const t=[];for(const e of c){const i=s?`${s} \u2192 ${e.name}`:e.name,r=u.has(e.type),d=!!e.routingRuleId&&!r;t.push({id:s?`${s}.${e.id}`:e.id,name:i,type:e.type,maxTokens:d?e.maxTokens:0,routingRuleId:e.routingRuleId,model:e.model,source:d?s?"subgraph":"node":"default",counted:d,nonLlm:!!e.routingRuleId&&r,_raw:e}),e.children&&e.children.length>0&&t.push(...p(e.children,i))}return t};async function _(c,s,t,e=new Map){const i=t?.name||"unknown",r=t?.graphId,d=t?.llm_overrides||{};if(!r)return{assistantId:s,assistantName:i,graphId:null,singlePassMax:0,nodes:[],warning:"Assistant has no graphId"};let g=[];try{g=await x(r)}catch(n){return{assistantId:s,assistantName:i,graphId:r,singlePassMax:0,nodes:[],warning:`Graph resolution failed: ${n.message}`}}const h=async n=>{if(e.has(n))return e.get(n);try{const a=(await c.search({index:y,body:{query:{bool:{must:[{term:{id:n}}]}},size:1}})).hits.hits[0]?._source||{},m={maxTokens:a.maxTokens??8e3,modelId:a.llmModelId||a.modelId};return e.set(n,m),m}catch{const o={maxTokens:8e3,modelId:void 0};return e.set(n,o),o}},l=p(g);for(const n of l){if(n.source==="subgraph"||u.has(n.type))continue;const o=d[n.type];if(!o)continue;const a=await h(o);n.maxTokens=a.maxTokens,n.routingRuleId=o,n.model=a.modelId,n.source="override",n.counted=!0}const f=l.reduce((n,o)=>n+(o.counted?o.maxTokens:0),0);return{assistantId:s,assistantName:i,graphId:r,graphName:l[0]?._raw?.graphName,singlePassMax:f,nodes:l.map(({_raw:n,...o})=>o)}}export{_ as projectAssistantTokens};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Client as U}from"@elastic/elasticsearch";import{config as _}from"../config";const T=new U(_.elasticsearch),y=".stkxp_chat_tools";function D(l,r){if(!r)return 0;const e=new Date(l.timestamp).getTime();return new Date(r.timestamp).getTime()-e}function F(l){if(!l.output)return!1;const r=JSON.stringify(l.output).toLowerCase();return r.includes("error")||r.includes("failed")||r.includes("exception")||r.includes("timeout")}async function M(l,r){try{const e={bool:{must:[]}};l&&e.bool.must.push({range:{createdAt:{gte:l.start,lte:l.end}}}),r&&e.bool.must.push({term:{username:r}});const h=(await T.search({index:y,body:{query:e.bool.must.length>0?e:{match_all:{}},size:1e4}})).hits.hits.map(t=>({id:t._id,...t._source})),g=new Map;h.forEach(t=>{t.tools?.forEach((s,n)=>{const a=s.name;g.has(a)||g.set(a,{totalCalls:0,failures:0,durations:[],lastUsed:s.timestamp,users:new Map});const c=g.get(a);c.totalCalls++,F(s)&&c.failures++;const p=t.tools?.[n+1];if(p){const f=D(s,p);f>0&&c.durations.push(f)}new Date(s.timestamp)>new Date(c.lastUsed)&&(c.lastUsed=s.timestamp);const d=c.users.get(t.username)||0;c.users.set(t.username,d+1)})});const o=[];return g.forEach((t,s)=>{const n=t.durations.length>0?t.durations.reduce((p,d)=>p+d,0)/t.durations.length:0,a=t.totalCalls>0?(t.totalCalls-t.failures)/t.totalCalls*100:100,c=Array.from(t.users.entries()).map(([p,d])=>({username:p,count:d})).sort((p,d)=>d.count-p.count).slice(0,5);o.push({name:s,totalCalls:t.totalCalls,successRate:parseFloat(a.toFixed(2)),avgDuration:parseFloat(n.toFixed(2)),failureCount:t.failures,lastUsed:t.lastUsed,topUsers:c})}),o.sort((t,s)=>s.totalCalls-t.totalCalls)}catch(e){throw console.error("Error getting tool usage stats:",e),e}}async function q(l){try{const r=await T.search({index:y,body:{query:{term:{runId:l}},size:1}});return r.hits.hits.length===0?[]:{id:r.hits.hits[0]._id,...r.hits.hits[0]._source}.tools||[]}catch(r){throw console.error("Error getting tool calls by run:",r),r}}async function z(l,r,e=100){try{const i={bool:{must:[]}};r&&i.bool.must.push({term:{username:r}});const g=(await T.search({index:y,body:{query:i.bool.must.length>0?i:{match_all:{}},size:1e4,sort:[{createdAt:{order:"desc",unmapped_type:"date"}}]}})).hits.hits.map(t=>({id:t._id,...t._source})),o=[];return g.forEach(t=>{t.tools?.forEach(s=>{l&&s.name!==l||F(s)&&o.push({runId:t.runId,chatId:t.chatId,username:t.username,toolName:s.name,timestamp:s.timestamp,input:s.input,output:s.output,error:JSON.stringify(s.output)})})}),o.slice(0,e)}catch(i){throw console.error("Error getting tool failures:",i),i}}async function J(l,r,e){try{const i={bool:{must:[]}};r&&i.bool.must.push({range:{createdAt:{gte:r.start,lte:r.end}}}),e&&i.bool.must.push({term:{username:e}});const g=(await T.search({index:y,body:{query:i.bool.must.length>0?i:{match_all:{}},size:1e4}})).hits.hits.map(u=>({id:u._id,...u._source})),o=[],t=new Map;let s=0;if(g.forEach(u=>{u.tools?.forEach((m,A)=>{if(m.name!==l)return;s++;const b=u.tools?.[A+1];if(b){const C=D(m,b);C>0&&o.push(C)}const x=new Date(m.timestamp).toISOString().slice(0,13)+":00:00";t.set(x,(t.get(x)||0)+1)})}),s===0)return null;o.sort((u,m)=>u-m);const n=o.length>0?o.reduce((u,m)=>u+m,0)/o.length:0,a=o.length>0?o[0]:0,c=o.length>0?o[o.length-1]:0,p=Math.floor(o.length*.5),d=Math.floor(o.length*.95),f=Math.floor(o.length*.99),w=o.length>0?o[p]:0,v=o.length>0?o[d]:0,E=o.length>0?o[f]:0,R=Array.from(t.entries()).map(([u,m])=>({timestamp:u,count:m})).sort((u,m)=>u.timestamp.localeCompare(m.timestamp));return{name:l,totalCalls:s,avgDuration:parseFloat(n.toFixed(2)),minDuration:parseFloat(a.toFixed(2)),maxDuration:parseFloat(c.toFixed(2)),p50Duration:parseFloat(w.toFixed(2)),p95Duration:parseFloat(v.toFixed(2)),p99Duration:parseFloat(E.toFixed(2)),callsOverTime:R}}catch(i){return console.error("Error getting tool performance:",i),null}}async function L(l,r){try{const e=await M(l,r);if(e.length===0)return{totalTools:0,totalCalls:0,avgSuccessRate:100,mostUsedTool:"N/A",leastUsedTool:"N/A",slowestTool:"N/A",fastestTool:"N/A"};const i=e.reduce((n,a)=>n+a.totalCalls,0),h=e.reduce((n,a)=>n+a.successRate,0)/e.length,g=e.reduce((n,a)=>a.totalCalls>n.totalCalls?a:n).name,o=e.reduce((n,a)=>a.totalCalls<n.totalCalls?a:n).name,t=e.reduce((n,a)=>a.avgDuration>n.avgDuration?a:n).name,s=e.filter(n=>n.avgDuration>0).reduce((n,a)=>a.avgDuration<n.avgDuration?a:n,e[0]).name;return{totalTools:e.length,totalCalls:i,avgSuccessRate:parseFloat(h.toFixed(2)),mostUsedTool:g,leastUsedTool:o,slowestTool:t,fastestTool:s}}catch(e){throw console.error("Error getting tool analytics:",e),e}}export{L as getToolAnalytics,q as getToolCallsByRun,z as getToolFailures,J as getToolPerformance,M as getToolUsageStats};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Client as p}from"@elastic/elasticsearch";import{config as u}from"../config";import{pruneHistory as w}from"./golden-questions-scoring";const o=new p(u.elasticsearch),c=".stkxp_tools",h=".stkxp_tool_metrics",r=".stkxp_tools_history",g=20;async function m(){try{if(await o.indices.exists({index:r}))return;await o.indices.create({index:r,body:{settings:{number_of_shards:1,number_of_replicas:1},mappings:{properties:{toolId:{type:"keyword"},toolName:{type:"keyword"},snapshot:{type:"object",enabled:!1},reason:{type:"keyword"},preChangeQ:{type:"float"},preChangeWindow:{type:"keyword"},createdBy:{type:"keyword"},createdAt:{type:"date"}}}}}),console.log(`[tool-history] created index ${r}`)}catch(e){throw console.error("[tool-history] failed to initialize index:",e),e}}async function _(e){try{const t=(await o.search({index:h,body:{query:{bool:{filter:[{term:{name:e}},{term:{window:"30d"}}]}},_source:["Q"],size:1}})).hits?.hits?.[0];return{q:t?._source?.Q??null,window:t?"30d":null}}catch{return{q:null,window:null}}}async function D(e,i,t){await m();const n=await o.get({index:c,id:e}),s=n._source?.name??e,{q:d,window:l}=await _(s),a={toolId:e,toolName:s,snapshot:n._source??{},reason:i,preChangeQ:d,preChangeWindow:l,createdBy:t,createdAt:new Date().toISOString()},y=await o.index({index:r,body:a,refresh:!0});return a.id=y._id,await x(e),a}async function x(e){const t=((await o.search({index:r,body:{query:{term:{toolId:e}},_source:["createdAt"],size:1e3}})).hits?.hits??[]).map(s=>({id:s._id,createdAt:s._source?.createdAt??""})),n=w(t,g);n.length!==0&&await o.bulk({operations:n.map(s=>({delete:{_index:r,_id:s}})),refresh:!0})}async function k(e,i){const n=(await o.get({index:r,id:i}))._source?.snapshot;if(!n)throw new Error("History snapshot not found");await o.index({index:c,id:e,body:n,refresh:!0})}async function O(e){return((await o.search({index:r,body:{query:{term:{toolId:e}},sort:[{createdAt:{order:"desc"}}],size:20}})).hits?.hits??[]).map(t=>({id:t._id,...t._source}))}export{m as initializeToolHistoryIndex,O as listToolHistory,k as rollbackToolVersion,D as snapshotToolVersion};
|