@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
package/README.md
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# `@stkxp/cli` — `stkxp export` / `stkxp deploy`
|
|
2
|
+
|
|
3
|
+
Take a Stack Expert **Team** out of a running `stkxp-app` instance as a single
|
|
4
|
+
encrypted bundle file, and redeploy it — assistants, graphs, prompts, tools,
|
|
5
|
+
platforms, credentials and all — standalone on any Elasticsearch cluster you
|
|
6
|
+
control, with its inbound webhook served locally.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install -g @stkxp/cli
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Four commands, two machines:
|
|
13
|
+
|
|
14
|
+
| Command | Runs where | Talks to |
|
|
15
|
+
|---------|------------|----------|
|
|
16
|
+
| `stkxp export` | anywhere with network access to the source app | the source `stkxp-app` REST API (`POST /api/teams/:id/export-encrypted`) |
|
|
17
|
+
| `stkxp deploy` | the target host | the target Elasticsearch cluster; bootstraps it, then serves the team webhook in the foreground |
|
|
18
|
+
| `stkxp bootstrap` | the target host | the target Elasticsearch cluster; writes documents, mints the webhook token, exits |
|
|
19
|
+
| `stkxp serve` | the target host | the target Elasticsearch cluster (read-only); serves the team webhook in the foreground forever |
|
|
20
|
+
|
|
21
|
+
`stkxp deploy` is `bootstrap` + `serve` run back to back as one command — the
|
|
22
|
+
simplest path for a manual, one-off deploy. Use `bootstrap`/`serve` as two
|
|
23
|
+
separate steps instead when something needs to *restart* the webhook process
|
|
24
|
+
without re-running the (ES-writing) bootstrap step every time — e.g. a
|
|
25
|
+
`docker compose` one-shot init service plus a `restart: unless-stopped` long-running
|
|
26
|
+
one, or a k8s Job/initContainer ahead of a Deployment. See
|
|
27
|
+
[`stkxp bootstrap` / `stkxp serve`](#stkxp-bootstrap--stkxp-serve) below.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## `stkxp export`
|
|
32
|
+
|
|
33
|
+
Exports the team and its full dependency closure. Every secret in the closure
|
|
34
|
+
(platform auth keys, LLM provider API keys, tool credentials, the team's
|
|
35
|
+
webhook token and MCP signing secret) is encrypted with your passphrase using
|
|
36
|
+
AES-256-GCM under a single scrypt-derived, per-bundle key. Everything else —
|
|
37
|
+
graph topology, prompts, tool definitions — stays plain, diffable JSON.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
export STKXP_SECRET='…' # or let the CLI prompt you
|
|
41
|
+
stkxp export \
|
|
42
|
+
--source-url https://app.example.com \
|
|
43
|
+
--token "$STKXP_JWT" \
|
|
44
|
+
--team AbCdEf1234567890 \
|
|
45
|
+
--out ./ops-team.bundle.json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
| Flag | Required | Description |
|
|
49
|
+
|------|:--------:|-------------|
|
|
50
|
+
| `--source-url <url>` | yes | Base URL of the source `stkxp-app` instance. |
|
|
51
|
+
| `--token <jwt>` | yes | JWT bearer token of the team's owner. |
|
|
52
|
+
| `--team <teamId>` | yes | Team ES document id to export. |
|
|
53
|
+
| `--secret <passphrase>` | no\* | Passphrase to encrypt secrets with (min 8 chars). |
|
|
54
|
+
| `--out <file>` | yes | Path to write the bundle to. Created with mode `0600`. |
|
|
55
|
+
|
|
56
|
+
\* See [Providing secrets](#providing-secrets) — falls back to `STKXP_SECRET`,
|
|
57
|
+
then an interactive prompt.
|
|
58
|
+
|
|
59
|
+
## `stkxp deploy`
|
|
60
|
+
|
|
61
|
+
Decrypts the bundle, bootstraps its documents into the target cluster's
|
|
62
|
+
`.stkxp_*` indices, mints a **fresh** webhook token for the deployed team
|
|
63
|
+
(the source instance's token is never reused), and stays in the foreground
|
|
64
|
+
serving that team's webhook.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
export STKXP_SECRET='…'
|
|
68
|
+
export STKXP_ES_PASSWORD='…'
|
|
69
|
+
stkxp deploy \
|
|
70
|
+
--team ./ops-team.bundle.json \
|
|
71
|
+
--es-url https://es.internal:9200 \
|
|
72
|
+
--es-user elastic \
|
|
73
|
+
--es-ca /etc/ssl/certs/internal-ca.pem \
|
|
74
|
+
--webhook-port 8081
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
| Flag | Required | Default | Description |
|
|
78
|
+
|------|:--------:|---------|-------------|
|
|
79
|
+
| `--team <bundlePath>` | yes | — | Path to the encrypted bundle file. |
|
|
80
|
+
| `--secret <passphrase>` | no\* | — | Passphrase used at export time. |
|
|
81
|
+
| `--es-url <url>` | yes | — | Target Elasticsearch URL. |
|
|
82
|
+
| `--es-user <user>` | yes | — | Target Elasticsearch username. |
|
|
83
|
+
| `--es-password <password>` | no\* | — | Target Elasticsearch password. |
|
|
84
|
+
| `--es-ca <path>` | no | — | PEM CA bundle for the target's certificate chain. |
|
|
85
|
+
| `--es-insecure` | no | off | Skip TLS certificate verification against the target. Opt-in escape hatch for self-signed clusters with no CA on hand; prefer `--es-ca`. |
|
|
86
|
+
| `--webhook-port <port>` | no | `8081` | Port to serve the webhook listener on. |
|
|
87
|
+
| `--webhook-host <host>` | no | `127.0.0.1` | Interface to bind the webhook to. Loopback-only by default; pass `0.0.0.0` to expose it (put a reverse proxy with TLS in front if you do). |
|
|
88
|
+
|
|
89
|
+
On success it prints the webhook URL and the freshly minted webhook token
|
|
90
|
+
(**shown once** — save it), then keeps running. Stopping the process stops the
|
|
91
|
+
webhook; the deployed data stays in Elasticsearch.
|
|
92
|
+
|
|
93
|
+
### Calling the deployed webhook
|
|
94
|
+
|
|
95
|
+
Authenticate with the `x-stkxp-webhook-token` header — **not** `Authorization:
|
|
96
|
+
Bearer`:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
curl -X POST http://localhost:8081/api/webhooks/team/<teamId> \
|
|
100
|
+
-H "Content-Type: application/json" \
|
|
101
|
+
-H "x-stkxp-webhook-token: <token from the deploy output>" \
|
|
102
|
+
-d '{"message": "…"}'
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
A successful call returns `202 Accepted` with a `runId`/`chatId` — the team
|
|
106
|
+
graph then runs in the background. **The deployed team must have a
|
|
107
|
+
`graphId`** (a `.stkxp_graphs` coordination graph attached); a team with only
|
|
108
|
+
`assistantIds` and no coordination graph will accept the call but the run
|
|
109
|
+
fails immediately with `"... has no graphId — webhook runs require a
|
|
110
|
+
coordination graph"`. Export a team that already has one attached, or attach
|
|
111
|
+
one before exporting.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## `stkxp bootstrap` / `stkxp serve`
|
|
116
|
+
|
|
117
|
+
The two halves of `stkxp deploy`, run as separate commands so a supervisor can
|
|
118
|
+
restart the webhook process without re-touching Elasticsearch on every
|
|
119
|
+
restart.
|
|
120
|
+
|
|
121
|
+
**`stkxp bootstrap`** decrypts the bundle, writes its documents into the
|
|
122
|
+
target's `.stkxp_*` indices, mints a webhook token if the target doesn't
|
|
123
|
+
already have one, prints the result as JSON, and exits — it never opens a
|
|
124
|
+
listener. **Idempotent**: re-running it against a target that's already
|
|
125
|
+
bootstrapped (`webhookEnabled` + a `webhookToken` already present on the team
|
|
126
|
+
doc) skips minting a new token — an existing secret is never re-shown — but
|
|
127
|
+
still re-upserts the closure's documents (harmless, same `_id`s), so re-running
|
|
128
|
+
it is the way to push an updated bundle's contents onto an already-deployed
|
|
129
|
+
target without invalidating the webhook token callers already have.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
export STKXP_SECRET='…'
|
|
133
|
+
export STKXP_ES_PASSWORD='…'
|
|
134
|
+
stkxp bootstrap \
|
|
135
|
+
--team ./ops-team.bundle.json \
|
|
136
|
+
--es-url https://es.internal:9200 \
|
|
137
|
+
--es-user elastic \
|
|
138
|
+
--es-ca /etc/ssl/certs/internal-ca.pem
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
| Flag | Required | Description |
|
|
142
|
+
|------|:--------:|-------------|
|
|
143
|
+
| `--team <bundlePath>` | yes | Path to the encrypted bundle file. |
|
|
144
|
+
| `--secret <passphrase>` | no\* | Passphrase used at export time. |
|
|
145
|
+
| `--es-url <url>` | yes | Target Elasticsearch URL. |
|
|
146
|
+
| `--es-user <user>` | yes | Target Elasticsearch username. |
|
|
147
|
+
| `--es-password <password>` | no\* | Target Elasticsearch password. |
|
|
148
|
+
| `--es-ca <path>` | no | PEM CA bundle for the target's certificate chain. |
|
|
149
|
+
| `--es-insecure` | no | Skip TLS certificate verification against the target. |
|
|
150
|
+
|
|
151
|
+
**`stkxp serve`** starts the webhook listener against an already-bootstrapped
|
|
152
|
+
target — it never writes to Elasticsearch itself, so it's safe to crash-loop
|
|
153
|
+
or restart under a supervisor; it just reconnects and keeps serving whatever
|
|
154
|
+
team(s) the target already has `webhookEnabled`. Run `stkxp bootstrap` first —
|
|
155
|
+
`serve` does not create any documents.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
export STKXP_ES_PASSWORD='…'
|
|
159
|
+
stkxp serve \
|
|
160
|
+
--es-url https://es.internal:9200 \
|
|
161
|
+
--es-user elastic \
|
|
162
|
+
--es-ca /etc/ssl/certs/internal-ca.pem \
|
|
163
|
+
--port 8081 \
|
|
164
|
+
--host 0.0.0.0
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
| Flag | Required | Default | Description |
|
|
168
|
+
|------|:--------:|---------|-------------|
|
|
169
|
+
| `--es-url <url>` | yes | — | Target Elasticsearch URL. |
|
|
170
|
+
| `--es-user <user>` | yes | — | Target Elasticsearch username. |
|
|
171
|
+
| `--es-password <password>` | no\* | — | Target Elasticsearch password. |
|
|
172
|
+
| `--es-ca <path>` | no | — | PEM CA bundle for the target's certificate chain. |
|
|
173
|
+
| `--es-insecure` | no | off | Skip TLS certificate verification against the target. |
|
|
174
|
+
| `--port <port>` | no | `8081` | Port to serve the webhook listener on. |
|
|
175
|
+
| `--host <host>` | no | `127.0.0.1` | Interface to bind the webhook listener to. Pass `0.0.0.0` inside a container so Docker's published port mapping can reach it — `127.0.0.1` inside a container is unreachable from outside it even with `-p` published. |
|
|
176
|
+
|
|
177
|
+
`serve` runs in the foreground and forwards `SIGINT`/`SIGTERM` to the
|
|
178
|
+
underlying webhook process so a supervisor's normal stop signal triggers a
|
|
179
|
+
graceful shutdown rather than an abrupt kill.
|
|
180
|
+
|
|
181
|
+
### Multiple teams on one cluster
|
|
182
|
+
|
|
183
|
+
Supported: `stkxp bootstrap` only creates a `.stkxp_*` index when it doesn't
|
|
184
|
+
already exist, and its idempotent re-mint check is scoped to the one
|
|
185
|
+
`teamId` being bootstrapped — running `stkxp bootstrap --team <bundle-a>`
|
|
186
|
+
then `stkxp bootstrap --team <bundle-b>` against the same cluster adds
|
|
187
|
+
team B's documents into the same indices without touching team A's. A single
|
|
188
|
+
`stkxp serve` then answers `/api/webhooks/team/:teamId` for **every**
|
|
189
|
+
`webhookEnabled` team on that cluster — the route isn't scoped to one team,
|
|
190
|
+
so one running `serve` process is enough for all of them.
|
|
191
|
+
|
|
192
|
+
The one thing this does *not* protect against: if two independently-exported
|
|
193
|
+
bundles happen to share a document `_id` (e.g. the same platform/tool/LLM
|
|
194
|
+
provider reused across both source teams) with genuinely *different*
|
|
195
|
+
content, the second bootstrap silently overwrites the first's copy — see
|
|
196
|
+
[the fresh-cluster limitation](#the-target-elasticsearch-cluster-must-be-freshempty)
|
|
197
|
+
below. Sharing a dependency that's byte-identical in both exports is fine.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Providing secrets
|
|
202
|
+
|
|
203
|
+
`--secret` and `--es-password` are **optional flags**, because anything passed
|
|
204
|
+
in `argv` is visible to every user on the box via `ps` / `/proc/<pid>/cmdline`
|
|
205
|
+
and gets written into your shell history. Each is resolved in this order:
|
|
206
|
+
|
|
207
|
+
1. the explicit CLI flag, if given;
|
|
208
|
+
2. an environment variable — `STKXP_SECRET` for `--secret`, `STKXP_ES_PASSWORD`
|
|
209
|
+
for `--es-password`;
|
|
210
|
+
3. an interactive, non-echoing prompt, if stdin is a TTY.
|
|
211
|
+
|
|
212
|
+
If none of the three yields a value the command errors out and does nothing.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Limitations
|
|
217
|
+
|
|
218
|
+
### The target Elasticsearch cluster must be fresh/empty
|
|
219
|
+
|
|
220
|
+
`stkxp deploy` writes every document in the bundle at its original `_id`.
|
|
221
|
+
Deploying **twice**, or deploying against a cluster that already holds
|
|
222
|
+
`.stkxp_*` data, **silently overwrites colliding documents by `_id`**. There is
|
|
223
|
+
no merge, no dedup, no "already exists" detection, and no confirmation prompt —
|
|
224
|
+
a second deploy of a modified bundle will clobber the first deploy's documents,
|
|
225
|
+
and a deploy into a live cluster will clobber whatever shares an id with it.
|
|
226
|
+
|
|
227
|
+
Treat each deploy as targeting a dedicated, empty cluster (or at minimum one
|
|
228
|
+
with no existing Stack Expert data). Re-deploying an updated bundle onto a
|
|
229
|
+
running deployment is **not** a supported upgrade path.
|
|
230
|
+
|
|
231
|
+
### Indices are bootstrapped with dynamic mapping
|
|
232
|
+
|
|
233
|
+
Deploy creates the `.stkxp_*` indices it needs with Elasticsearch's default
|
|
234
|
+
dynamic mapping rather than the application's real per-entity mappings.
|
|
235
|
+
Consequences on a standalone deploy:
|
|
236
|
+
|
|
237
|
+
- **No semantic search.** Fields backed by `semantic_text` / ELSER-style
|
|
238
|
+
inference in a full `stkxp-app` install are plain text here; features that
|
|
239
|
+
depend on semantic retrieval degrade to lexical matching or return nothing.
|
|
240
|
+
- **Approximate field typing.** Exact `keyword` vs `text` typing, analyzers,
|
|
241
|
+
`index: false` flags and other mapping details are inferred from the first
|
|
242
|
+
document seen instead of being declared, so some queries that rely on precise
|
|
243
|
+
typing (exact-term filters, sorting, aggregations on analyzed fields) may
|
|
244
|
+
behave differently than on the source instance.
|
|
245
|
+
|
|
246
|
+
This is a deliberate v1 scope decision, not a bug: the team's runtime path
|
|
247
|
+
(webhook → graph execution → tools) works, but the deployment is not a
|
|
248
|
+
byte-for-byte replica of the source cluster's schema.
|
|
249
|
+
|
|
250
|
+
### Other v1 scope notes
|
|
251
|
+
|
|
252
|
+
- Neither `deploy` nor `serve` is supervised by this CLI itself — no PM2/systemd
|
|
253
|
+
unit, no Docker image shipped. Wrap `stkxp bootstrap` + `stkxp serve` in your
|
|
254
|
+
own supervisor (docker-compose, k8s, systemd) if you need survival across a
|
|
255
|
+
reboot or crash; `serve` is specifically designed be restart-safe for this
|
|
256
|
+
(see [`stkxp bootstrap` / `stkxp serve`](#stkxp-bootstrap--stkxp-serve)).
|
|
257
|
+
- The webhook is served over plain HTTP on the bound interface. Front it with a
|
|
258
|
+
TLS-terminating reverse proxy before exposing it beyond loopback.
|
|
259
|
+
- **Only the webhook façade exists.** The original design also envisioned MCP
|
|
260
|
+
and WebSocket façades (`--mcp-port` / `--ws-port`) for a fully protocol-agnostic
|
|
261
|
+
standalone deployment — neither is implemented; `stkxp deploy` has no such
|
|
262
|
+
flags. Not scheduled.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Status
|
|
267
|
+
|
|
268
|
+
Exercised end-to-end against a live source `stkxp-app` and a separate target
|
|
269
|
+
Elasticsearch cluster (2026-09-16): export → deploy → bootstrap →
|
|
270
|
+
authenticated webhook call → run accepted and logged. That run surfaced (and
|
|
271
|
+
fixed) module-resolution and TLS-propagation bugs that only appeared once the
|
|
272
|
+
CLI ran standalone rather than under unit tests — see the main repo's git
|
|
273
|
+
history around `db62f56` if you hit something similar.
|
package/bin/stkxp.mjs
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// packages/cli/bin/stkxp.mjs
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { runExport } from "../src/export.mjs";
|
|
5
|
+
import { runDeployCommand } from "../src/deploy.mjs";
|
|
6
|
+
import { runBootstrapCommand } from "../src/bootstrap.mjs";
|
|
7
|
+
import { runServeCommand } from "../src/serve.mjs";
|
|
8
|
+
import { resolveSecret } from "../src/secret-input.mjs";
|
|
9
|
+
|
|
10
|
+
const program = new Command();
|
|
11
|
+
program.name("stkxp").description("Export and deploy a Stack Expert Team standalone");
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.command("export")
|
|
15
|
+
.description("Export a Team and its whole dependency closure as an encrypted bundle file")
|
|
16
|
+
.requiredOption("--source-url <url>", "Base URL of the source stkxp-app instance")
|
|
17
|
+
.requiredOption("--token <jwt>", "JWT bearer token of the team's owner")
|
|
18
|
+
.requiredOption("--team <teamId>", "Team ES document id to export")
|
|
19
|
+
.option(
|
|
20
|
+
"--secret <passphrase>",
|
|
21
|
+
"Passphrase to encrypt secrets with (min 8 chars). Prefer the STKXP_SECRET env var or the interactive prompt — an argv value is visible in `ps` and shell history",
|
|
22
|
+
)
|
|
23
|
+
.requiredOption("--out <file>", "Path to write the encrypted bundle to (created mode 0600)")
|
|
24
|
+
.action(async (opts) => {
|
|
25
|
+
try {
|
|
26
|
+
const secret = await resolveSecret({
|
|
27
|
+
flagValue: opts.secret,
|
|
28
|
+
envVar: "STKXP_SECRET",
|
|
29
|
+
promptLabel: "Bundle passphrase: ",
|
|
30
|
+
flagName: "--secret",
|
|
31
|
+
});
|
|
32
|
+
const result = await runExport({
|
|
33
|
+
sourceUrl: opts.sourceUrl,
|
|
34
|
+
token: opts.token,
|
|
35
|
+
teamId: opts.team,
|
|
36
|
+
secret,
|
|
37
|
+
outFile: opts.out,
|
|
38
|
+
});
|
|
39
|
+
console.log(`Exported "${result.rootName}" (${result.totalDocs} docs) to ${result.outFile}`);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.error(`stkxp export failed: ${e.message}`);
|
|
42
|
+
process.exitCode = 1;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
program
|
|
47
|
+
.command("deploy")
|
|
48
|
+
.description(
|
|
49
|
+
"Deploy an encrypted Team bundle onto a target Elasticsearch cluster and serve its webhook. " +
|
|
50
|
+
"The target must be a FRESH cluster — colliding .stkxp_* documents are overwritten by _id, with no merge or dedup (see README).",
|
|
51
|
+
)
|
|
52
|
+
.requiredOption("--team <bundlePath>", "Path to the encrypted bundle file")
|
|
53
|
+
.option(
|
|
54
|
+
"--secret <passphrase>",
|
|
55
|
+
"Passphrase used at export time. Prefer the STKXP_SECRET env var or the interactive prompt — an argv value is visible in `ps` and shell history",
|
|
56
|
+
)
|
|
57
|
+
.requiredOption("--es-url <url>", "Target Elasticsearch URL")
|
|
58
|
+
.requiredOption("--es-user <user>", "Target Elasticsearch username")
|
|
59
|
+
.option(
|
|
60
|
+
"--es-password <password>",
|
|
61
|
+
"Target Elasticsearch password. Prefer the STKXP_ES_PASSWORD env var or the interactive prompt — an argv value is visible in `ps` and shell history",
|
|
62
|
+
)
|
|
63
|
+
.option("--es-ca <path>", "Path to a PEM CA bundle for the target Elasticsearch certificate chain")
|
|
64
|
+
.option("--es-insecure", "Skip TLS certificate verification against the target Elasticsearch (not recommended)")
|
|
65
|
+
.option("--webhook-port <port>", "Port to serve the webhook listener on", "8081")
|
|
66
|
+
.option("--webhook-host <host>", "Interface to bind the webhook listener to", "127.0.0.1")
|
|
67
|
+
.action(async (opts) => {
|
|
68
|
+
try {
|
|
69
|
+
const secret = await resolveSecret({
|
|
70
|
+
flagValue: opts.secret,
|
|
71
|
+
envVar: "STKXP_SECRET",
|
|
72
|
+
promptLabel: "Bundle passphrase: ",
|
|
73
|
+
flagName: "--secret",
|
|
74
|
+
});
|
|
75
|
+
const esPassword = await resolveSecret({
|
|
76
|
+
flagValue: opts.esPassword,
|
|
77
|
+
envVar: "STKXP_ES_PASSWORD",
|
|
78
|
+
promptLabel: "Target Elasticsearch password: ",
|
|
79
|
+
flagName: "--es-password",
|
|
80
|
+
});
|
|
81
|
+
const result = await runDeployCommand({
|
|
82
|
+
bundlePath: opts.team,
|
|
83
|
+
secret,
|
|
84
|
+
esUrl: opts.esUrl,
|
|
85
|
+
esUser: opts.esUser,
|
|
86
|
+
esPassword,
|
|
87
|
+
esCaPath: opts.esCa,
|
|
88
|
+
esInsecure: opts.esInsecure === true,
|
|
89
|
+
webhookPort: parseInt(opts.webhookPort, 10),
|
|
90
|
+
webhookHost: opts.webhookHost,
|
|
91
|
+
});
|
|
92
|
+
console.log(`Deployed "${result.rootName}" — webhook listening at ${result.webhookUrl}`);
|
|
93
|
+
console.log(`Webhook token (save this, shown once): ${result.webhookToken}`);
|
|
94
|
+
console.log(`Indices created: ${result.indicesCreated.join(", ") || "(none, already existed)"}`);
|
|
95
|
+
console.log(`Documents indexed: ${result.docsIndexed}`);
|
|
96
|
+
} catch (e) {
|
|
97
|
+
console.error(`stkxp deploy failed: ${e.message}`);
|
|
98
|
+
process.exitCode = 1;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
program
|
|
103
|
+
.command("bootstrap")
|
|
104
|
+
.description(
|
|
105
|
+
"Bootstrap an encrypted Team bundle onto a target Elasticsearch cluster WITHOUT serving the webhook. " +
|
|
106
|
+
"Idempotent — safe to re-run against an already-bootstrapped target (skips re-minting the webhook token). " +
|
|
107
|
+
"Pair with `stkxp serve` as separate init/long-running steps (e.g. a docker-compose one-shot service + a restart-safe service).",
|
|
108
|
+
)
|
|
109
|
+
.requiredOption("--team <bundlePath>", "Path to the encrypted bundle file")
|
|
110
|
+
.option(
|
|
111
|
+
"--secret <passphrase>",
|
|
112
|
+
"Passphrase used at export time. Prefer the STKXP_SECRET env var or the interactive prompt — an argv value is visible in `ps` and shell history",
|
|
113
|
+
)
|
|
114
|
+
.requiredOption("--es-url <url>", "Target Elasticsearch URL")
|
|
115
|
+
.requiredOption("--es-user <user>", "Target Elasticsearch username")
|
|
116
|
+
.option(
|
|
117
|
+
"--es-password <password>",
|
|
118
|
+
"Target Elasticsearch password. Prefer the STKXP_ES_PASSWORD env var or the interactive prompt — an argv value is visible in `ps` and shell history",
|
|
119
|
+
)
|
|
120
|
+
.option("--es-ca <path>", "Path to a PEM CA bundle for the target Elasticsearch certificate chain")
|
|
121
|
+
.option("--es-insecure", "Skip TLS certificate verification against the target Elasticsearch (not recommended)")
|
|
122
|
+
.action(async (opts) => {
|
|
123
|
+
try {
|
|
124
|
+
const secret = await resolveSecret({
|
|
125
|
+
flagValue: opts.secret,
|
|
126
|
+
envVar: "STKXP_SECRET",
|
|
127
|
+
promptLabel: "Bundle passphrase: ",
|
|
128
|
+
flagName: "--secret",
|
|
129
|
+
});
|
|
130
|
+
const esPassword = await resolveSecret({
|
|
131
|
+
flagValue: opts.esPassword,
|
|
132
|
+
envVar: "STKXP_ES_PASSWORD",
|
|
133
|
+
promptLabel: "Target Elasticsearch password: ",
|
|
134
|
+
flagName: "--es-password",
|
|
135
|
+
});
|
|
136
|
+
const result = await runBootstrapCommand({
|
|
137
|
+
bundlePath: opts.team,
|
|
138
|
+
secret,
|
|
139
|
+
esUrl: opts.esUrl,
|
|
140
|
+
esUser: opts.esUser,
|
|
141
|
+
esPassword,
|
|
142
|
+
esCaPath: opts.esCa,
|
|
143
|
+
esInsecure: opts.esInsecure === true,
|
|
144
|
+
});
|
|
145
|
+
if (result.alreadyBootstrapped) {
|
|
146
|
+
console.log(`Team ${result.teamId} was already bootstrapped on this target — skipped re-minting the webhook token.`);
|
|
147
|
+
} else {
|
|
148
|
+
console.log(`Bootstrapped "${result.rootName}" (team ${result.teamId})`);
|
|
149
|
+
console.log(`Webhook token (save this, shown once): ${result.webhookToken}`);
|
|
150
|
+
}
|
|
151
|
+
console.log(`Indices created: ${result.indicesCreated.join(", ") || "(none, already existed)"}`);
|
|
152
|
+
console.log(`Documents indexed: ${result.docsIndexed}`);
|
|
153
|
+
} catch (e) {
|
|
154
|
+
console.error(`stkxp bootstrap failed: ${e.message}`);
|
|
155
|
+
process.exitCode = 1;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
program
|
|
160
|
+
.command("serve")
|
|
161
|
+
.description(
|
|
162
|
+
"Serve the standalone Team webhook against an already-bootstrapped target Elasticsearch cluster. " +
|
|
163
|
+
"Run `stkxp bootstrap` first. Long-running and restart-safe — never writes to ES, so a crash/restart is harmless.",
|
|
164
|
+
)
|
|
165
|
+
.requiredOption("--es-url <url>", "Target Elasticsearch URL")
|
|
166
|
+
.requiredOption("--es-user <user>", "Target Elasticsearch username")
|
|
167
|
+
.option(
|
|
168
|
+
"--es-password <password>",
|
|
169
|
+
"Target Elasticsearch password. Prefer the STKXP_ES_PASSWORD env var or the interactive prompt — an argv value is visible in `ps` and shell history",
|
|
170
|
+
)
|
|
171
|
+
.option("--es-ca <path>", "Path to a PEM CA bundle for the target Elasticsearch certificate chain")
|
|
172
|
+
.option("--es-insecure", "Skip TLS certificate verification against the target Elasticsearch (not recommended)")
|
|
173
|
+
.option("--port <port>", "Port to serve the webhook listener on", "8081")
|
|
174
|
+
.option("--host <host>", "Interface to bind the webhook listener to", "127.0.0.1")
|
|
175
|
+
.action(async (opts) => {
|
|
176
|
+
try {
|
|
177
|
+
const esPassword = await resolveSecret({
|
|
178
|
+
flagValue: opts.esPassword,
|
|
179
|
+
envVar: "STKXP_ES_PASSWORD",
|
|
180
|
+
promptLabel: "Target Elasticsearch password: ",
|
|
181
|
+
flagName: "--es-password",
|
|
182
|
+
});
|
|
183
|
+
await runServeCommand({
|
|
184
|
+
esUrl: opts.esUrl,
|
|
185
|
+
esUser: opts.esUser,
|
|
186
|
+
esPassword,
|
|
187
|
+
esCaPath: opts.esCa,
|
|
188
|
+
esInsecure: opts.esInsecure === true,
|
|
189
|
+
port: parseInt(opts.port, 10),
|
|
190
|
+
host: opts.host,
|
|
191
|
+
});
|
|
192
|
+
} catch (e) {
|
|
193
|
+
console.error(`stkxp serve failed: ${e.message}`);
|
|
194
|
+
process.exitCode = 1;
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
program.parseAsync(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stkxp/cli",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Export a Stack Expert Team as an encrypted, standalone-deployable bundle, and redeploy it on any Elasticsearch cluster.",
|
|
7
|
+
"bin": {
|
|
8
|
+
"stkxp": "./bin/stkxp.mjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"README.md",
|
|
12
|
+
"bin",
|
|
13
|
+
"src",
|
|
14
|
+
"vendor"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"prepack": "node scripts/prepack.mjs"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@ai-sdk/openai": "^1.3.24",
|
|
21
|
+
"@asteasolutions/zod-to-openapi": "^7.3.4",
|
|
22
|
+
"@elastic/datemath": "5.0.3",
|
|
23
|
+
"@elastic/ebt": "^1.4.1",
|
|
24
|
+
"@elastic/ecs": "^8.11.5",
|
|
25
|
+
"@elastic/elasticsearch": "^8.19.1",
|
|
26
|
+
"@elastic/ems-client": "8.6.3",
|
|
27
|
+
"@elastic/filesaver": "1.1.2",
|
|
28
|
+
"@elastic/node-crypto": "^1.2.3",
|
|
29
|
+
"@elastic/numeral": "^2.5.1",
|
|
30
|
+
"@elastic/request-crypto": "^2.0.3",
|
|
31
|
+
"@h1deya/langchain-google-genai-ex": "^0.0.1",
|
|
32
|
+
"@langchain/anthropic": "^1.5.1",
|
|
33
|
+
"@langchain/community": "^1.1.13",
|
|
34
|
+
"@langchain/core": "^1.2.1",
|
|
35
|
+
"@langchain/google-genai": "^2.2.0",
|
|
36
|
+
"@langchain/langgraph": "^1.4.7",
|
|
37
|
+
"@langchain/langgraph-checkpoint": "^1.0.0",
|
|
38
|
+
"@langchain/langgraph-sdk": "^1.6.0",
|
|
39
|
+
"@langchain/mcp-adapters": "^1.1.3",
|
|
40
|
+
"@langchain/openai": "^1.5.3",
|
|
41
|
+
"@langchain/tavily": "^1.2.0",
|
|
42
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
43
|
+
"@nats-io/nats-core": "^3.4.0",
|
|
44
|
+
"@nats-io/transport-node": "^3.4.0",
|
|
45
|
+
"@types/js-yaml": "^4.0.9",
|
|
46
|
+
"@types/jspdf": "^1.3.3",
|
|
47
|
+
"@types/leaflet": "^1.9.21",
|
|
48
|
+
"ai": "^4.3.19",
|
|
49
|
+
"archiver": "^8.0.0",
|
|
50
|
+
"axios": "^1.13.5",
|
|
51
|
+
"body-parser": "^2.2.2",
|
|
52
|
+
"class-variance-authority": "^0.7.1",
|
|
53
|
+
"clsx": "^2.1.1",
|
|
54
|
+
"convert": "^5.14.1",
|
|
55
|
+
"dagre": "^0.8.5",
|
|
56
|
+
"dotenv": "^17.2.4",
|
|
57
|
+
"echarts": "^6.0.0",
|
|
58
|
+
"elkjs": "0.9.3",
|
|
59
|
+
"express": "^5.2.1",
|
|
60
|
+
"happy-dom": "^20.6.0",
|
|
61
|
+
"html2canvas": "^1.4.1",
|
|
62
|
+
"i18next": "^25.8.13",
|
|
63
|
+
"ioredis": "^5.9.2",
|
|
64
|
+
"js-yaml": "^4.1.1",
|
|
65
|
+
"jsonata": "^2.0.6",
|
|
66
|
+
"jsonwebtoken": "^9.0.3",
|
|
67
|
+
"jspdf": "^3.0.4",
|
|
68
|
+
"juice": "^12.1.1",
|
|
69
|
+
"langchain": "^1.5.2",
|
|
70
|
+
"langfuse": "^3.38.6",
|
|
71
|
+
"langfuse-langchain": "^3.38.6",
|
|
72
|
+
"leaflet": "^1.9.4",
|
|
73
|
+
"lodash": "^4.17.23",
|
|
74
|
+
"luxon": "^3.7.2",
|
|
75
|
+
"moment": "2.30.1",
|
|
76
|
+
"moment-timezone": "^0.6.0",
|
|
77
|
+
"morgan": "^1.10.1",
|
|
78
|
+
"mysql2": "^3.16.3",
|
|
79
|
+
"nodemailer": "^7.0.13",
|
|
80
|
+
"partial-json": "^0.1.7",
|
|
81
|
+
"pdf-parse": "2.4.5",
|
|
82
|
+
"pg": "^8.18.0",
|
|
83
|
+
"resend": "^4.8.0",
|
|
84
|
+
"slugify": "^1.6.6",
|
|
85
|
+
"stream-json": "^1.9.1",
|
|
86
|
+
"stripe": "^22.0.1",
|
|
87
|
+
"swagger-ui-express": "^5.0.1",
|
|
88
|
+
"undici": "^7.21.0",
|
|
89
|
+
"uuid": "^11.1.0",
|
|
90
|
+
"winston": "^3.19.0",
|
|
91
|
+
"winston-daily-rotate-file": "^5.0.0",
|
|
92
|
+
"ws": "^8.19.0",
|
|
93
|
+
"zod": "^3.25.76",
|
|
94
|
+
"commander": "^12.0.0",
|
|
95
|
+
"tsx": "^4.19.0"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// packages/cli/src/bootstrap.mjs
|
|
2
|
+
//
|
|
3
|
+
// `stkxp bootstrap` — decrypts a bundle and bootstraps its closure onto a
|
|
4
|
+
// target Elasticsearch cluster, WITHOUT serving the webhook. Meant for a
|
|
5
|
+
// one-shot init step (docker-compose one-shot service, k8s Job/initContainer)
|
|
6
|
+
// ahead of a separately-scheduled long-running `stkxp serve`. Idempotent: a
|
|
7
|
+
// re-run against an already-bootstrapped target skips re-minting the webhook
|
|
8
|
+
// token (see server/entrypoints/cli-deploy.ts's bootstrapTeam()).
|
|
9
|
+
//
|
|
10
|
+
// Spawns the vendored server/entrypoints/cli-bootstrap-run.js under tsx —
|
|
11
|
+
// same rationale as packages/cli/src/deploy.mjs (see its header for why a
|
|
12
|
+
// child process, and why tsx is resolved via require.resolve("tsx/cli")).
|
|
13
|
+
import { readFile } from "node:fs/promises";
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { spawnAndAwaitJsonResult, resolveTsxCli } from "./deploy.mjs";
|
|
18
|
+
|
|
19
|
+
const CLI_ROOT = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
20
|
+
|
|
21
|
+
/** Must stay byte-identical to RESULT_SENTINEL in server/entrypoints/cli-bootstrap-run.ts. */
|
|
22
|
+
export const RESULT_SENTINEL = "__STKXP_BOOTSTRAP_RESULT__";
|
|
23
|
+
|
|
24
|
+
export async function runBootstrapCommand({ bundlePath, secret, esUrl, esUser, esPassword, esCaPath, esInsecure }) {
|
|
25
|
+
const bundle = JSON.parse(await readFile(bundlePath, "utf8"));
|
|
26
|
+
|
|
27
|
+
const runnerScript = path.join(CLI_ROOT, "vendor", "dist-server", "entrypoints", "cli-bootstrap-run.js");
|
|
28
|
+
|
|
29
|
+
return spawnAndAwaitJsonResult(
|
|
30
|
+
process.execPath,
|
|
31
|
+
[resolveTsxCli(), runnerScript],
|
|
32
|
+
{
|
|
33
|
+
input: JSON.stringify({ bundle, secret, esUrl, esUser, esPassword, esCaPath, esInsecure }),
|
|
34
|
+
},
|
|
35
|
+
RESULT_SENTINEL,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// packages/cli/src/bootstrap.test.mjs
|
|
2
|
+
//
|
|
3
|
+
// spawnAndAwaitJsonResult's own resolution/rejection contract is already
|
|
4
|
+
// covered end-to-end in deploy.test.mjs (bootstrap.mjs reuses that same
|
|
5
|
+
// function, just parameterized with its own sentinel) — this file only
|
|
6
|
+
// covers what's specific to runBootstrapCommand: reading the bundle file,
|
|
7
|
+
// picking the right vendored runner script, and passing its own
|
|
8
|
+
// RESULT_SENTINEL (not deploy.mjs's) through to the shared spawn helper.
|
|
9
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const CLI_ROOT = path.dirname(fileURLToPath(new URL(".", import.meta.url)));
|
|
14
|
+
|
|
15
|
+
vi.mock("node:fs/promises", () => ({
|
|
16
|
+
readFile: vi.fn(),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const mockSpawnAndAwaitJsonResult = vi.hoisted(() => vi.fn());
|
|
20
|
+
vi.mock("./deploy.mjs", () => ({
|
|
21
|
+
spawnAndAwaitJsonResult: mockSpawnAndAwaitJsonResult,
|
|
22
|
+
resolveTsxCli: () => "/fake/tsx/dist/cli.mjs",
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
import { readFile } from "node:fs/promises";
|
|
26
|
+
import { runBootstrapCommand, RESULT_SENTINEL } from "./bootstrap.mjs";
|
|
27
|
+
|
|
28
|
+
describe("RESULT_SENTINEL", () => {
|
|
29
|
+
it("is its own sentinel, distinct from deploy.mjs's", () => {
|
|
30
|
+
expect(RESULT_SENTINEL).toBe("__STKXP_BOOTSTRAP_RESULT__");
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("runBootstrapCommand", () => {
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
vi.clearAllMocks();
|
|
37
|
+
mockSpawnAndAwaitJsonResult.mockResolvedValue({ teamId: "team-1", alreadyBootstrapped: false });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("reads the bundle file, spawns the bootstrap runner under tsx, and passes its own sentinel", async () => {
|
|
41
|
+
readFile.mockResolvedValue(JSON.stringify({ envelope: "v2" }));
|
|
42
|
+
|
|
43
|
+
const result = await runBootstrapCommand({
|
|
44
|
+
bundlePath: "./ops.bundle.json",
|
|
45
|
+
secret: "s3cr3t",
|
|
46
|
+
esUrl: "https://es:9200",
|
|
47
|
+
esUser: "elastic",
|
|
48
|
+
esPassword: "pw",
|
|
49
|
+
esCaPath: "/ca.pem",
|
|
50
|
+
esInsecure: false,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
expect(readFile).toHaveBeenCalledWith("./ops.bundle.json", "utf8");
|
|
54
|
+
expect(result).toEqual({ teamId: "team-1", alreadyBootstrapped: false });
|
|
55
|
+
|
|
56
|
+
expect(mockSpawnAndAwaitJsonResult).toHaveBeenCalledTimes(1);
|
|
57
|
+
const [command, args, opts, sentinel] = mockSpawnAndAwaitJsonResult.mock.calls[0];
|
|
58
|
+
expect(command).toBe(process.execPath);
|
|
59
|
+
expect(args).toEqual(["/fake/tsx/dist/cli.mjs", path.join(CLI_ROOT, "vendor", "dist-server", "entrypoints", "cli-bootstrap-run.js")]);
|
|
60
|
+
expect(sentinel).toBe(RESULT_SENTINEL);
|
|
61
|
+
|
|
62
|
+
const payload = JSON.parse(opts.input);
|
|
63
|
+
expect(payload).toEqual({
|
|
64
|
+
bundle: { envelope: "v2" },
|
|
65
|
+
secret: "s3cr3t",
|
|
66
|
+
esUrl: "https://es:9200",
|
|
67
|
+
esUser: "elastic",
|
|
68
|
+
esPassword: "pw",
|
|
69
|
+
esCaPath: "/ca.pem",
|
|
70
|
+
esInsecure: false,
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|