mcp4openapi 0.2.8 → 0.3.1
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 +143 -63
- package/dist/scripts/validate-profile.js +3 -3
- package/dist/scripts/validate-profile.js.map +1 -1
- package/dist/src/argument-normalizer.d.ts +5 -0
- package/dist/src/argument-normalizer.d.ts.map +1 -0
- package/dist/src/argument-normalizer.js +61 -0
- package/dist/src/argument-normalizer.js.map +1 -0
- package/dist/src/auth/oauth-provider.d.ts +131 -0
- package/dist/src/auth/oauth-provider.d.ts.map +1 -0
- package/dist/src/auth/oauth-provider.js +839 -0
- package/dist/src/auth/oauth-provider.js.map +1 -0
- package/dist/src/cli-config.d.ts +9 -0
- package/dist/src/cli-config.d.ts.map +1 -0
- package/dist/src/cli-config.js +111 -0
- package/dist/src/cli-config.js.map +1 -0
- package/dist/src/core/cli-config.d.ts +9 -0
- package/dist/src/core/cli-config.d.ts.map +1 -0
- package/dist/src/core/cli-config.js +125 -0
- package/dist/src/core/cli-config.js.map +1 -0
- package/dist/src/core/constants.d.ts +86 -0
- package/dist/src/core/constants.d.ts.map +1 -0
- package/dist/src/core/constants.js +86 -0
- package/dist/src/core/constants.js.map +1 -0
- package/dist/src/core/errors.d.ts +59 -0
- package/dist/src/core/errors.d.ts.map +1 -0
- package/dist/src/core/errors.js +119 -0
- package/dist/src/core/errors.js.map +1 -0
- package/dist/src/core/filtering.d.ts +19 -0
- package/dist/src/core/filtering.d.ts.map +1 -0
- package/dist/src/core/filtering.js +292 -0
- package/dist/src/core/filtering.js.map +1 -0
- package/dist/src/core/index.d.ts +26 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +276 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/core/lib.d.ts +8 -0
- package/dist/src/core/lib.d.ts.map +1 -0
- package/dist/src/core/lib.js +7 -0
- package/dist/src/core/lib.js.map +1 -0
- package/dist/src/core/logger.d.ts +59 -0
- package/dist/src/core/logger.d.ts.map +1 -0
- package/dist/src/core/logger.js +197 -0
- package/dist/src/core/logger.js.map +1 -0
- package/dist/src/core/metrics.d.ts +97 -0
- package/dist/src/core/metrics.d.ts.map +1 -0
- package/dist/src/core/metrics.js +273 -0
- package/dist/src/core/metrics.js.map +1 -0
- package/dist/src/core/naming-warnings.d.ts +23 -0
- package/dist/src/core/naming-warnings.d.ts.map +1 -0
- package/dist/src/core/naming-warnings.js +83 -0
- package/dist/src/core/naming-warnings.js.map +1 -0
- package/dist/src/core/naming.d.ts +58 -0
- package/dist/src/core/naming.d.ts.map +1 -0
- package/dist/src/core/naming.js +510 -0
- package/dist/src/core/naming.js.map +1 -0
- package/dist/src/errors.d.ts +6 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +15 -6
- package/dist/src/errors.js.map +1 -1
- package/dist/src/filtering.d.ts +19 -0
- package/dist/src/filtering.d.ts.map +1 -0
- package/dist/src/filtering.js +292 -0
- package/dist/src/filtering.js.map +1 -0
- package/dist/src/generated-schemas.d.ts +290 -79
- package/dist/src/generated-schemas.d.ts.map +1 -1
- package/dist/src/generated-schemas.js +17 -2
- package/dist/src/generated-schemas.js.map +1 -1
- package/dist/src/http-transport-config.d.ts +6 -0
- package/dist/src/http-transport-config.d.ts.map +1 -0
- package/dist/src/http-transport-config.js +47 -0
- package/dist/src/http-transport-config.js.map +1 -0
- package/dist/src/http-transport.d.ts +63 -13
- package/dist/src/http-transport.d.ts.map +1 -1
- package/dist/src/http-transport.js +1045 -482
- package/dist/src/http-transport.js.map +1 -1
- package/dist/src/index.d.ts +1 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -170
- package/dist/src/index.js.map +1 -1
- package/dist/src/interceptors.d.ts +1 -0
- package/dist/src/interceptors.d.ts.map +1 -1
- package/dist/src/interceptors.js +73 -63
- package/dist/src/interceptors.js.map +1 -1
- package/dist/src/lib.d.ts +1 -7
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +1 -6
- package/dist/src/lib.js.map +1 -1
- package/dist/src/logger.d.ts +5 -0
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/logger.js +9 -1
- package/dist/src/logger.js.map +1 -1
- package/dist/src/mcp/mcp-server-manager.d.ts +20 -0
- package/dist/src/mcp/mcp-server-manager.d.ts.map +1 -0
- package/dist/src/mcp/mcp-server-manager.js +38 -0
- package/dist/src/mcp/mcp-server-manager.js.map +1 -0
- package/dist/src/mcp/mcp-server.d.ts +205 -0
- package/dist/src/mcp/mcp-server.d.ts.map +1 -0
- package/dist/src/mcp/mcp-server.js +1473 -0
- package/dist/src/mcp/mcp-server.js.map +1 -0
- package/dist/src/mcp-server-manager.d.ts +20 -0
- package/dist/src/mcp-server-manager.d.ts.map +1 -0
- package/dist/src/mcp-server-manager.js +38 -0
- package/dist/src/mcp-server-manager.js.map +1 -0
- package/dist/src/mcp-server.d.ts +28 -0
- package/dist/src/mcp-server.d.ts.map +1 -1
- package/dist/src/mcp-server.js +406 -109
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/metrics.d.ts +11 -0
- package/dist/src/metrics.d.ts.map +1 -1
- package/dist/src/metrics.js +61 -0
- package/dist/src/metrics.js.map +1 -1
- package/dist/src/oauth-provider.d.ts +5 -0
- package/dist/src/oauth-provider.d.ts.map +1 -1
- package/dist/src/oauth-provider.js +29 -1
- package/dist/src/oauth-provider.js.map +1 -1
- package/dist/src/openapi/openapi-parser.d.ts +70 -0
- package/dist/src/openapi/openapi-parser.d.ts.map +1 -0
- package/dist/src/openapi/openapi-parser.js +458 -0
- package/dist/src/openapi/openapi-parser.js.map +1 -0
- package/dist/src/profile/profile-loader.d.ts +78 -0
- package/dist/src/profile/profile-loader.d.ts.map +1 -0
- package/dist/src/profile/profile-loader.js +490 -0
- package/dist/src/profile/profile-loader.js.map +1 -0
- package/dist/src/profile/profile-registry.d.ts +19 -0
- package/dist/src/profile/profile-registry.d.ts.map +1 -0
- package/dist/src/profile/profile-registry.js +43 -0
- package/dist/src/profile/profile-registry.js.map +1 -0
- package/dist/src/profile/profile-resolver.d.ts +41 -0
- package/dist/src/profile/profile-resolver.d.ts.map +1 -0
- package/dist/src/profile/profile-resolver.js +324 -0
- package/dist/src/profile/profile-resolver.js.map +1 -0
- package/dist/src/profile/startup-profile.d.ts +17 -0
- package/dist/src/profile/startup-profile.d.ts.map +1 -0
- package/dist/src/profile/startup-profile.js +30 -0
- package/dist/src/profile/startup-profile.js.map +1 -0
- package/dist/src/profile/startup-validation.d.ts +11 -0
- package/dist/src/profile/startup-validation.d.ts.map +1 -0
- package/dist/src/profile/startup-validation.js +21 -0
- package/dist/src/profile/startup-validation.js.map +1 -0
- package/dist/src/profile-loader.d.ts +1 -0
- package/dist/src/profile-loader.d.ts.map +1 -1
- package/dist/src/profile-loader.js +14 -3
- package/dist/src/profile-loader.js.map +1 -1
- package/dist/src/profile-registry.d.ts +18 -0
- package/dist/src/profile-registry.d.ts.map +1 -0
- package/dist/src/profile-registry.js +26 -0
- package/dist/src/profile-registry.js.map +1 -0
- package/dist/src/profile-resolver.d.ts +19 -0
- package/dist/src/profile-resolver.d.ts.map +1 -0
- package/dist/src/profile-resolver.js +167 -0
- package/dist/src/profile-resolver.js.map +1 -0
- package/dist/src/proxy-executor.d.ts.map +1 -1
- package/dist/src/proxy-executor.js +7 -0
- package/dist/src/proxy-executor.js.map +1 -1
- package/dist/src/startup-profile.d.ts +17 -0
- package/dist/src/startup-profile.d.ts.map +1 -0
- package/dist/src/startup-profile.js +30 -0
- package/dist/src/startup-profile.js.map +1 -0
- package/dist/src/startup-validation.d.ts +11 -0
- package/dist/src/startup-validation.d.ts.map +1 -0
- package/dist/src/startup-validation.js +21 -0
- package/dist/src/startup-validation.js.map +1 -0
- package/dist/src/testing/dynamic-mock-server.d.ts +24 -0
- package/dist/src/testing/dynamic-mock-server.d.ts.map +1 -0
- package/dist/src/testing/dynamic-mock-server.js +138 -0
- package/dist/src/testing/dynamic-mock-server.js.map +1 -0
- package/dist/src/testing/request-assertions.d.ts +5 -0
- package/dist/src/testing/request-assertions.d.ts.map +1 -0
- package/dist/src/testing/request-assertions.js +165 -0
- package/dist/src/testing/request-assertions.js.map +1 -0
- package/dist/src/testing/template-utils.d.ts +10 -0
- package/dist/src/testing/template-utils.d.ts.map +1 -0
- package/dist/src/testing/template-utils.js +72 -0
- package/dist/src/testing/template-utils.js.map +1 -0
- package/dist/src/testing/test-http-utils.d.ts +1 -1
- package/dist/src/testing/test-http-utils.d.ts.map +1 -1
- package/dist/src/testing/test-http-utils.js +1 -1
- package/dist/src/testing/test-http-utils.js.map +1 -1
- package/dist/src/testing/test-loader.d.ts +6 -0
- package/dist/src/testing/test-loader.d.ts.map +1 -0
- package/dist/src/testing/test-loader.js +212 -0
- package/dist/src/testing/test-loader.js.map +1 -0
- package/dist/src/testing/test-schema.d.ts +1270 -0
- package/dist/src/testing/test-schema.d.ts.map +1 -0
- package/dist/src/testing/test-schema.js +76 -0
- package/dist/src/testing/test-schema.js.map +1 -0
- package/dist/src/tool-filter/compat.d.ts +49 -0
- package/dist/src/tool-filter/compat.d.ts.map +1 -0
- package/dist/src/tool-filter/compat.js +72 -0
- package/dist/src/tool-filter/compat.js.map +1 -0
- package/dist/src/tool-filter/config/env-config-parser.d.ts +38 -0
- package/dist/src/tool-filter/config/env-config-parser.d.ts.map +1 -0
- package/dist/src/tool-filter/config/env-config-parser.js +103 -0
- package/dist/src/tool-filter/config/env-config-parser.js.map +1 -0
- package/dist/src/tool-filter/config/header-config-parser.d.ts +37 -0
- package/dist/src/tool-filter/config/header-config-parser.d.ts.map +1 -0
- package/dist/src/tool-filter/config/header-config-parser.js +118 -0
- package/dist/src/tool-filter/config/header-config-parser.js.map +1 -0
- package/dist/src/tool-filter/errors.d.ts +18 -0
- package/dist/src/tool-filter/errors.d.ts.map +1 -0
- package/dist/src/tool-filter/errors.js +21 -0
- package/dist/src/tool-filter/errors.js.map +1 -0
- package/dist/src/tool-filter/filter/filter-engine.d.ts +45 -0
- package/dist/src/tool-filter/filter/filter-engine.d.ts.map +1 -0
- package/dist/src/tool-filter/filter/filter-engine.js +94 -0
- package/dist/src/tool-filter/filter/filter-engine.js.map +1 -0
- package/dist/src/tool-filter/filter/filter-rules.d.ts +44 -0
- package/dist/src/tool-filter/filter/filter-rules.d.ts.map +1 -0
- package/dist/src/tool-filter/filter/filter-rules.js +72 -0
- package/dist/src/tool-filter/filter/filter-rules.js.map +1 -0
- package/dist/src/tool-filter/filter/global-tool-filter.d.ts +40 -0
- package/dist/src/tool-filter/filter/global-tool-filter.d.ts.map +1 -0
- package/dist/src/tool-filter/filter/global-tool-filter.js +92 -0
- package/dist/src/tool-filter/filter/global-tool-filter.js.map +1 -0
- package/dist/src/tool-filter/filter/session-tool-filter.d.ts +29 -0
- package/dist/src/tool-filter/filter/session-tool-filter.d.ts.map +1 -0
- package/dist/src/tool-filter/filter/session-tool-filter.js +69 -0
- package/dist/src/tool-filter/filter/session-tool-filter.js.map +1 -0
- package/dist/src/tool-filter/index.d.ts +25 -0
- package/dist/src/tool-filter/index.d.ts.map +1 -0
- package/dist/src/tool-filter/index.js +30 -0
- package/dist/src/tool-filter/index.js.map +1 -0
- package/dist/src/tool-filter/integration/tool-filter-service.d.ts +44 -0
- package/dist/src/tool-filter/integration/tool-filter-service.d.ts.map +1 -0
- package/dist/src/tool-filter/integration/tool-filter-service.js +68 -0
- package/dist/src/tool-filter/integration/tool-filter-service.js.map +1 -0
- package/dist/src/tool-filter/operation/operation-classifier.d.ts +20 -0
- package/dist/src/tool-filter/operation/operation-classifier.d.ts.map +1 -0
- package/dist/src/tool-filter/operation/operation-classifier.js +26 -0
- package/dist/src/tool-filter/operation/operation-classifier.js.map +1 -0
- package/dist/src/tool-filter/operation/operation-detector.d.ts +30 -0
- package/dist/src/tool-filter/operation/operation-detector.d.ts.map +1 -0
- package/dist/src/tool-filter/operation/operation-detector.js +96 -0
- package/dist/src/tool-filter/operation/operation-detector.js.map +1 -0
- package/dist/src/tool-filter/operation/operation-resolver.d.ts +22 -0
- package/dist/src/tool-filter/operation/operation-resolver.d.ts.map +1 -0
- package/dist/src/tool-filter/operation/operation-resolver.js +32 -0
- package/dist/src/tool-filter/operation/operation-resolver.js.map +1 -0
- package/dist/src/tool-filter/regex/regex-compiler.d.ts +22 -0
- package/dist/src/tool-filter/regex/regex-compiler.d.ts.map +1 -0
- package/dist/src/tool-filter/regex/regex-compiler.js +56 -0
- package/dist/src/tool-filter/regex/regex-compiler.js.map +1 -0
- package/dist/src/tool-filter/regex/regex-validator.d.ts +24 -0
- package/dist/src/tool-filter/regex/regex-validator.d.ts.map +1 -0
- package/dist/src/tool-filter/regex/regex-validator.js +58 -0
- package/dist/src/tool-filter/regex/regex-validator.js.map +1 -0
- package/dist/src/tool-filter/types.d.ts +92 -0
- package/dist/src/tool-filter/types.d.ts.map +1 -0
- package/dist/src/tool-filter/types.js +5 -0
- package/dist/src/tool-filter/types.js.map +1 -0
- package/dist/src/tool-filter/utils.d.ts +11 -0
- package/dist/src/tool-filter/utils.d.ts.map +1 -0
- package/dist/src/tool-filter/utils.js +13 -0
- package/dist/src/tool-filter/utils.js.map +1 -0
- package/dist/src/tool-filter.d.ts +65 -0
- package/dist/src/tool-filter.d.ts.map +1 -0
- package/dist/src/tool-filter.js +471 -0
- package/dist/src/tool-filter.js.map +1 -0
- package/dist/src/tool-generator.d.ts +1 -0
- package/dist/src/tool-generator.d.ts.map +1 -1
- package/dist/src/tool-generator.js +15 -6
- package/dist/src/tool-generator.js.map +1 -1
- package/dist/src/tooling/composite-executor.d.ts +77 -0
- package/dist/src/tooling/composite-executor.d.ts.map +1 -0
- package/dist/src/tooling/composite-executor.js +198 -0
- package/dist/src/tooling/composite-executor.js.map +1 -0
- package/dist/src/tooling/dag-executor.d.ts +49 -0
- package/dist/src/tooling/dag-executor.d.ts.map +1 -0
- package/dist/src/tooling/dag-executor.js +138 -0
- package/dist/src/tooling/dag-executor.js.map +1 -0
- package/dist/src/tooling/proxy-executor.d.ts +86 -0
- package/dist/src/tooling/proxy-executor.d.ts.map +1 -0
- package/dist/src/tooling/proxy-executor.js +501 -0
- package/dist/src/tooling/proxy-executor.js.map +1 -0
- package/dist/src/tooling/tool-generator.d.ts +67 -0
- package/dist/src/tooling/tool-generator.d.ts.map +1 -0
- package/dist/src/tooling/tool-generator.js +222 -0
- package/dist/src/tooling/tool-generator.js.map +1 -0
- package/dist/src/transport/http-client-factory.d.ts +65 -0
- package/dist/src/transport/http-client-factory.d.ts.map +1 -0
- package/dist/src/transport/http-client-factory.js +143 -0
- package/dist/src/transport/http-client-factory.js.map +1 -0
- package/dist/src/transport/http-transport-config.d.ts +6 -0
- package/dist/src/transport/http-transport-config.d.ts.map +1 -0
- package/dist/src/transport/http-transport-config.js +63 -0
- package/dist/src/transport/http-transport-config.js.map +1 -0
- package/dist/src/transport/http-transport.d.ts +329 -0
- package/dist/src/transport/http-transport.d.ts.map +1 -0
- package/dist/src/transport/http-transport.js +2584 -0
- package/dist/src/transport/http-transport.js.map +1 -0
- package/dist/src/transport/interceptors.d.ts +119 -0
- package/dist/src/transport/interceptors.d.ts.map +1 -0
- package/dist/src/transport/interceptors.js +413 -0
- package/dist/src/transport/interceptors.js.map +1 -0
- package/dist/src/transport/profile-index.d.ts +84 -0
- package/dist/src/transport/profile-index.d.ts.map +1 -0
- package/dist/src/transport/profile-index.js +405 -0
- package/dist/src/transport/profile-index.js.map +1 -0
- package/dist/src/types/http-transport.d.ts +26 -0
- package/dist/src/types/http-transport.d.ts.map +1 -1
- package/dist/src/types/openapi.d.ts +3 -0
- package/dist/src/types/openapi.d.ts.map +1 -1
- package/dist/src/types/profile.d.ts +16 -1
- package/dist/src/types/profile.d.ts.map +1 -1
- package/dist/src/validation/argument-normalizer.d.ts +6 -0
- package/dist/src/validation/argument-normalizer.d.ts.map +1 -0
- package/dist/src/validation/argument-normalizer.js +70 -0
- package/dist/src/validation/argument-normalizer.js.map +1 -0
- package/dist/src/validation/jsonrpc-validator.d.ts +27 -0
- package/dist/src/validation/jsonrpc-validator.d.ts.map +1 -0
- package/dist/src/validation/jsonrpc-validator.js +58 -0
- package/dist/src/validation/jsonrpc-validator.js.map +1 -0
- package/dist/src/validation/schema-validator.d.ts +30 -0
- package/dist/src/validation/schema-validator.d.ts.map +1 -0
- package/dist/src/validation/schema-validator.js +128 -0
- package/dist/src/validation/schema-validator.js.map +1 -0
- package/dist/src/validation/validation-utils.d.ts +49 -0
- package/dist/src/validation/validation-utils.d.ts.map +1 -0
- package/dist/src/validation/validation-utils.js +139 -0
- package/dist/src/validation/validation-utils.js.map +1 -0
- package/html/profile-index.html +386 -0
- package/package.json +10 -3
- package/profile-schema.json +77 -3
- package/profiles/gitlab/developer-profile-oauth.json +1520 -0
- package/profiles/gitlab/developer-profile-oauth.test.json +3432 -0
- package/profiles/gitlab/developer-profile.json +1508 -0
- package/profiles/gitlab/developer-profile.test.json +3432 -0
- package/profiles/gitlab/openapi.yaml +6891 -0
- package/profiles/n8n/openapi.yaml +2441 -0
- package/profiles/n8n/profile-optimized.json +965 -0
- package/profiles/n8n/profile-optimized.test.json +1078 -0
- package/profiles/n8n/profile.json +1033 -0
- package/profiles/n8n/profile.test.json +983 -0
- package/profiles/n8n-nodes/openapi.yaml +24 -0
- package/profiles/n8n-nodes/profile-nodes.json +44 -0
- package/profiles/n8n-nodes/profile-nodes.test.json +91 -0
- package/profiles/semgrep/openapi.yaml +4706 -0
- package/profiles/semgrep/profile.json +692 -0
- package/profiles/semgrep/profile.test.json +471 -0
- package/profiles/youtrack/openapi.json +16976 -0
- package/profiles/youtrack/profile.json +608 -0
- package/profiles/youtrack/profile.test.json +1926 -0
- package/dist/src/testing/fixtures.d.ts +0 -684
- package/dist/src/testing/fixtures.d.ts.map +0 -1
- package/dist/src/testing/fixtures.js +0 -528
- package/dist/src/testing/fixtures.js.map +0 -1
- package/dist/src/testing/mock-gitlab-server.d.ts +0 -43
- package/dist/src/testing/mock-gitlab-server.d.ts.map +0 -1
- package/dist/src/testing/mock-gitlab-server.js +0 -1026
- package/dist/src/testing/mock-gitlab-server.js.map +0 -1
- package/dist/src/testing/mock-semgrep-server.d.ts +0 -32
- package/dist/src/testing/mock-semgrep-server.d.ts.map +0 -1
- package/dist/src/testing/mock-semgrep-server.js +0 -213
- package/dist/src/testing/mock-semgrep-server.js.map +0 -1
- package/dist/src/testing/mock-youtrack-server.d.ts +0 -11
- package/dist/src/testing/mock-youtrack-server.d.ts.map +0 -1
- package/dist/src/testing/mock-youtrack-server.js +0 -152
- package/dist/src/testing/mock-youtrack-server.js.map +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composite action executor for chaining API calls
|
|
3
|
+
*
|
|
4
|
+
* Why: Reduces roundtrips by fetching related data in sequence (e.g., MR + comments).
|
|
5
|
+
* Aggregates results into single JSON structure as defined by store_as paths.
|
|
6
|
+
*/
|
|
7
|
+
import type { CompositeStep } from '../types/profile.js';
|
|
8
|
+
import type { HttpClient } from '../transport/interceptors.js';
|
|
9
|
+
import { OpenAPIParser } from '../openapi/openapi-parser.js';
|
|
10
|
+
export interface CompositeResult {
|
|
11
|
+
data: Record<string, unknown>;
|
|
12
|
+
completed_steps: number;
|
|
13
|
+
total_steps: number;
|
|
14
|
+
errors?: StepError[];
|
|
15
|
+
}
|
|
16
|
+
export interface StepError {
|
|
17
|
+
step_index: number;
|
|
18
|
+
step_call: string;
|
|
19
|
+
error: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class CompositeExecutor {
|
|
23
|
+
private parser;
|
|
24
|
+
private httpClient?;
|
|
25
|
+
private parameterAliases;
|
|
26
|
+
constructor(parser: OpenAPIParser, httpClient?: HttpClient | undefined, parameterAliases?: Record<string, string[]>);
|
|
27
|
+
/**
|
|
28
|
+
* Execute a series of API calls and merge results
|
|
29
|
+
*
|
|
30
|
+
* Why parallel: Steps may have dependencies, but independent steps can run concurrently.
|
|
31
|
+
* Uses DAG analysis to determine safe parallelization while maintaining correctness.
|
|
32
|
+
*
|
|
33
|
+
* Supports partial results: If allowPartial=true, continues after errors and returns
|
|
34
|
+
* what was completed. Useful for composite actions where some data is better than none.
|
|
35
|
+
*/
|
|
36
|
+
execute(steps: CompositeStep[], args: Record<string, unknown>, allowPartial?: boolean, httpClient?: HttpClient): Promise<CompositeResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Execute single composite step (extracted for parallel execution)
|
|
39
|
+
*
|
|
40
|
+
* @param step The composite step to execute
|
|
41
|
+
* @param stepIndex Original index for error reporting
|
|
42
|
+
* @param args Arguments for parameter substitution
|
|
43
|
+
* @param httpClient Optional HTTP client override
|
|
44
|
+
* @returns Promise resolving to HTTP response
|
|
45
|
+
*/
|
|
46
|
+
private executeStep;
|
|
47
|
+
/**
|
|
48
|
+
* Parse composite step call syntax
|
|
49
|
+
*
|
|
50
|
+
* Format: "GET /projects/{id}/merge_requests/{iid}"
|
|
51
|
+
*/
|
|
52
|
+
private parseCall;
|
|
53
|
+
/**
|
|
54
|
+
* Resolve path template with actual values
|
|
55
|
+
*
|
|
56
|
+
* Example: "/projects/{id}" + {id: "123"} => "/projects/123"
|
|
57
|
+
* Supports parameter_aliases: {project_id: "123"} can map to {id} if configured
|
|
58
|
+
*/
|
|
59
|
+
private resolvePath;
|
|
60
|
+
/**
|
|
61
|
+
* Extract query parameters from args based on operation definition
|
|
62
|
+
*/
|
|
63
|
+
private extractQueryParams;
|
|
64
|
+
/**
|
|
65
|
+
* Store value at JSONPath-like location
|
|
66
|
+
*
|
|
67
|
+
* Why nested: Allows semantic structure (comments belong under merge_request object).
|
|
68
|
+
*
|
|
69
|
+
* Examples:
|
|
70
|
+
* - "merge_request" => { merge_request: value }
|
|
71
|
+
* - "merge_request.comments" => { merge_request: { comments: value } }
|
|
72
|
+
*
|
|
73
|
+
* Validates path navigation to prevent overwriting non-object values.
|
|
74
|
+
*/
|
|
75
|
+
private storeResult;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=composite-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite-executor.d.ts","sourceRoot":"","sources":["../../../src/tooling/composite-executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAI7D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU,CAAC;IACnB,OAAO,CAAC,gBAAgB;gBAFhB,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,UAAU,YAAA,EACvB,gBAAgB,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAM;IAGzD;;;;;;;;OAQG;IACG,OAAO,CACX,KAAK,EAAE,aAAa,EAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,YAAY,GAAE,OAAe,EAC7B,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,eAAe,CAAC;IA+D3B;;;;;;;;OAQG;YACW,WAAW;IA6BzB;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAQjB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAsBnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,WAAW;CAwCpB"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composite action executor for chaining API calls
|
|
3
|
+
*
|
|
4
|
+
* Why: Reduces roundtrips by fetching related data in sequence (e.g., MR + comments).
|
|
5
|
+
* Aggregates results into single JSON structure as defined by store_as paths.
|
|
6
|
+
*/
|
|
7
|
+
import { DAGExecutor } from './dag-executor.js';
|
|
8
|
+
import { isSafePropertyName } from '../validation/validation-utils.js';
|
|
9
|
+
export class CompositeExecutor {
|
|
10
|
+
constructor(parser, httpClient, parameterAliases = {}) {
|
|
11
|
+
this.parser = parser;
|
|
12
|
+
this.httpClient = httpClient;
|
|
13
|
+
this.parameterAliases = parameterAliases;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Execute a series of API calls and merge results
|
|
17
|
+
*
|
|
18
|
+
* Why parallel: Steps may have dependencies, but independent steps can run concurrently.
|
|
19
|
+
* Uses DAG analysis to determine safe parallelization while maintaining correctness.
|
|
20
|
+
*
|
|
21
|
+
* Supports partial results: If allowPartial=true, continues after errors and returns
|
|
22
|
+
* what was completed. Useful for composite actions where some data is better than none.
|
|
23
|
+
*/
|
|
24
|
+
async execute(steps, args, allowPartial = false, httpClient) {
|
|
25
|
+
// Analyze DAG and get execution levels
|
|
26
|
+
const executionLevels = DAGExecutor.topologicalSort(steps);
|
|
27
|
+
const result = {};
|
|
28
|
+
const errors = [];
|
|
29
|
+
let completedSteps = 0;
|
|
30
|
+
// Execute level by level (each level can run in parallel)
|
|
31
|
+
for (const level of executionLevels) {
|
|
32
|
+
// Execute all steps in current level concurrently
|
|
33
|
+
const levelPromises = level.steps.map((step, levelIndex) => this.executeStep(step, level.stepIndices[levelIndex], args, httpClient));
|
|
34
|
+
// Wait for all steps in this level to complete
|
|
35
|
+
const levelResults = await Promise.allSettled(levelPromises);
|
|
36
|
+
// Process results
|
|
37
|
+
for (let i = 0; i < levelResults.length; i++) {
|
|
38
|
+
const promiseResult = levelResults[i];
|
|
39
|
+
const step = level.steps[i];
|
|
40
|
+
const originalStepIndex = level.stepIndices[i];
|
|
41
|
+
if (promiseResult.status === 'fulfilled') {
|
|
42
|
+
// Step completed successfully
|
|
43
|
+
const response = promiseResult.value;
|
|
44
|
+
this.storeResult(result, step.store_as, response.body);
|
|
45
|
+
completedSteps++;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Step failed
|
|
49
|
+
const error = promiseResult.reason;
|
|
50
|
+
const stepError = {
|
|
51
|
+
step_index: originalStepIndex,
|
|
52
|
+
step_call: step.call,
|
|
53
|
+
error: error instanceof Error ? error.message : String(error),
|
|
54
|
+
timestamp: new Date().toISOString(),
|
|
55
|
+
};
|
|
56
|
+
errors.push(stepError);
|
|
57
|
+
// Store error in result for debugging
|
|
58
|
+
this.storeResult(result, `${step.store_as}_error`, stepError);
|
|
59
|
+
if (!allowPartial) {
|
|
60
|
+
throw new Error(`Composite step ${originalStepIndex + 1}/${steps.length} failed: ${stepError.error}\n` +
|
|
61
|
+
`Completed steps: ${completedSteps}\n` +
|
|
62
|
+
`Failed step: ${step.call}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
data: result,
|
|
69
|
+
completed_steps: completedSteps,
|
|
70
|
+
total_steps: steps.length,
|
|
71
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Execute single composite step (extracted for parallel execution)
|
|
76
|
+
*
|
|
77
|
+
* @param step The composite step to execute
|
|
78
|
+
* @param stepIndex Original index for error reporting
|
|
79
|
+
* @param args Arguments for parameter substitution
|
|
80
|
+
* @param httpClient Optional HTTP client override
|
|
81
|
+
* @returns Promise resolving to HTTP response
|
|
82
|
+
*/
|
|
83
|
+
async executeStep(step, stepIndex, args, httpClient) {
|
|
84
|
+
const { method, path, operation } = this.parseCall(step.call);
|
|
85
|
+
if (!operation) {
|
|
86
|
+
throw new Error(`Operation not found for call: ${step.call}`);
|
|
87
|
+
}
|
|
88
|
+
// Substitute path parameters from args
|
|
89
|
+
const resolvedPath = this.resolvePath(path, args);
|
|
90
|
+
// Execute request
|
|
91
|
+
const client = httpClient || this.httpClient;
|
|
92
|
+
if (!client) {
|
|
93
|
+
throw new Error('HTTP client not provided');
|
|
94
|
+
}
|
|
95
|
+
const response = await client.request(method, resolvedPath, {
|
|
96
|
+
params: this.extractQueryParams(operation, args),
|
|
97
|
+
operationId: operation.operationId,
|
|
98
|
+
});
|
|
99
|
+
return response;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Parse composite step call syntax
|
|
103
|
+
*
|
|
104
|
+
* Format: "GET /projects/{id}/merge_requests/{iid}"
|
|
105
|
+
*/
|
|
106
|
+
parseCall(call) {
|
|
107
|
+
const [method, path] = call.split(' ');
|
|
108
|
+
const pathInfo = this.parser.getPath(path);
|
|
109
|
+
const operation = pathInfo?.operations[method.toLowerCase()];
|
|
110
|
+
return { method, path, operation };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Resolve path template with actual values
|
|
114
|
+
*
|
|
115
|
+
* Example: "/projects/{id}" + {id: "123"} => "/projects/123"
|
|
116
|
+
* Supports parameter_aliases: {project_id: "123"} can map to {id} if configured
|
|
117
|
+
*/
|
|
118
|
+
resolvePath(template, args) {
|
|
119
|
+
return template.replace(/\{(\w+)\}/g, (_, key) => {
|
|
120
|
+
// Try direct match first
|
|
121
|
+
if (args[key] !== undefined) {
|
|
122
|
+
return encodeURIComponent(String(args[key]));
|
|
123
|
+
}
|
|
124
|
+
// Try aliases from profile
|
|
125
|
+
const possibleAliases = this.parameterAliases[key] || [];
|
|
126
|
+
for (const alias of possibleAliases) {
|
|
127
|
+
if (args[alias] !== undefined) {
|
|
128
|
+
return encodeURIComponent(String(args[alias]));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
throw new Error(`Missing path parameter: ${key}` +
|
|
132
|
+
(possibleAliases.length > 0 ? `. Tried aliases: ${possibleAliases.join(', ')}` : ''));
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Extract query parameters from args based on operation definition
|
|
137
|
+
*/
|
|
138
|
+
extractQueryParams(operation, args) {
|
|
139
|
+
const params = {};
|
|
140
|
+
for (const param of operation.parameters) {
|
|
141
|
+
if (param.in === 'query' && args[param.name] !== undefined) {
|
|
142
|
+
const value = args[param.name];
|
|
143
|
+
// Pass arrays as-is for HttpClient serialization
|
|
144
|
+
if (Array.isArray(value)) {
|
|
145
|
+
params[param.name] = value.map(String);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
params[param.name] = String(value);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return params;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Store value at JSONPath-like location
|
|
156
|
+
*
|
|
157
|
+
* Why nested: Allows semantic structure (comments belong under merge_request object).
|
|
158
|
+
*
|
|
159
|
+
* Examples:
|
|
160
|
+
* - "merge_request" => { merge_request: value }
|
|
161
|
+
* - "merge_request.comments" => { merge_request: { comments: value } }
|
|
162
|
+
*
|
|
163
|
+
* Validates path navigation to prevent overwriting non-object values.
|
|
164
|
+
*/
|
|
165
|
+
storeResult(target, path, value) {
|
|
166
|
+
const parts = path.split('.');
|
|
167
|
+
let current = target;
|
|
168
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
169
|
+
const part = parts[i];
|
|
170
|
+
// Prevent prototype pollution
|
|
171
|
+
if (!isSafePropertyName(part)) {
|
|
172
|
+
throw new Error(`Invalid property name in path: ${part}`);
|
|
173
|
+
}
|
|
174
|
+
const existing = current[part];
|
|
175
|
+
// Validate we can navigate through this path
|
|
176
|
+
if (existing !== undefined && (typeof existing !== 'object' || existing === null)) {
|
|
177
|
+
throw new Error(`Cannot store at path '${path}': ` +
|
|
178
|
+
`'${parts.slice(0, i + 1).join('.')}' is ${typeof existing}, not an object`);
|
|
179
|
+
}
|
|
180
|
+
if (!current[part]) {
|
|
181
|
+
// nosemgrep: javascript.lang.security.audit.prototype-pollution.prototype-pollution-loop.prototype-pollution-loop
|
|
182
|
+
// Guarded by isSafePropertyName(part) above; safe dynamic key after validation.
|
|
183
|
+
current[part] = {};
|
|
184
|
+
}
|
|
185
|
+
// nosemgrep: javascript.lang.security.audit.prototype-pollution.prototype-pollution-loop.prototype-pollution-loop
|
|
186
|
+
// Guarded by isSafePropertyName(part) above; safe dynamic key after validation.
|
|
187
|
+
current = current[part];
|
|
188
|
+
}
|
|
189
|
+
const finalKey = parts[parts.length - 1];
|
|
190
|
+
if (!isSafePropertyName(finalKey)) {
|
|
191
|
+
throw new Error(`Invalid property name in path: ${finalKey}`);
|
|
192
|
+
}
|
|
193
|
+
// codeql[js/prototype-pollution-utility]
|
|
194
|
+
// Guarded by isSafePropertyName above.
|
|
195
|
+
current[finalKey] = value;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=composite-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite-executor.js","sourceRoot":"","sources":["../../../src/tooling/composite-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAG Execution Engine for Composite Steps
|
|
3
|
+
*
|
|
4
|
+
* Why: Enables parallel execution of independent composite steps
|
|
5
|
+
* while maintaining correct dependency order.
|
|
6
|
+
*
|
|
7
|
+
* Uses Kahn's algorithm for topological sorting - BFS-based approach
|
|
8
|
+
* that detects cycles and determines execution levels.
|
|
9
|
+
*/
|
|
10
|
+
import type { CompositeStep } from '../types/profile.js';
|
|
11
|
+
/**
|
|
12
|
+
* Execution level containing steps that can run in parallel
|
|
13
|
+
*/
|
|
14
|
+
export interface ExecutionLevel {
|
|
15
|
+
steps: CompositeStep[];
|
|
16
|
+
stepIndices: number[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Topological sort result for DAG execution
|
|
20
|
+
*/
|
|
21
|
+
export interface TopologicalSortResult {
|
|
22
|
+
levels: ExecutionLevel[];
|
|
23
|
+
hasCycles: boolean;
|
|
24
|
+
errorMessage?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Execute composite steps with DAG-based parallelization
|
|
28
|
+
*
|
|
29
|
+
* Why: Some steps may depend on others (e.g., get MR ID, then fetch comments).
|
|
30
|
+
* Independent steps can run in parallel for better performance.
|
|
31
|
+
*/
|
|
32
|
+
export declare class DAGExecutor {
|
|
33
|
+
/**
|
|
34
|
+
* Sort composite steps into execution levels using Kahn's algorithm
|
|
35
|
+
*
|
|
36
|
+
* @param steps Composite steps with optional depends_on
|
|
37
|
+
* @returns Execution levels where each level can run in parallel
|
|
38
|
+
* @throws Error if cycles detected or invalid dependencies
|
|
39
|
+
*/
|
|
40
|
+
static topologicalSort(steps: CompositeStep[]): ExecutionLevel[];
|
|
41
|
+
/**
|
|
42
|
+
* Analyze DAG structure without throwing
|
|
43
|
+
*
|
|
44
|
+
* @param steps Composite steps to analyze
|
|
45
|
+
* @returns Analysis result with levels or error info
|
|
46
|
+
*/
|
|
47
|
+
static analyzeDAG(steps: CompositeStep[]): TopologicalSortResult;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=dag-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-executor.d.ts","sourceRoot":"","sources":["../../../src/tooling/dag-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,qBAAa,WAAW;IACtB;;;;;;OAMG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,cAAc,EAAE;IAQhE;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,qBAAqB;CAoHjE"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAG Execution Engine for Composite Steps
|
|
3
|
+
*
|
|
4
|
+
* Why: Enables parallel execution of independent composite steps
|
|
5
|
+
* while maintaining correct dependency order.
|
|
6
|
+
*
|
|
7
|
+
* Uses Kahn's algorithm for topological sorting - BFS-based approach
|
|
8
|
+
* that detects cycles and determines execution levels.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Execute composite steps with DAG-based parallelization
|
|
12
|
+
*
|
|
13
|
+
* Why: Some steps may depend on others (e.g., get MR ID, then fetch comments).
|
|
14
|
+
* Independent steps can run in parallel for better performance.
|
|
15
|
+
*/
|
|
16
|
+
export class DAGExecutor {
|
|
17
|
+
/**
|
|
18
|
+
* Sort composite steps into execution levels using Kahn's algorithm
|
|
19
|
+
*
|
|
20
|
+
* @param steps Composite steps with optional depends_on
|
|
21
|
+
* @returns Execution levels where each level can run in parallel
|
|
22
|
+
* @throws Error if cycles detected or invalid dependencies
|
|
23
|
+
*/
|
|
24
|
+
static topologicalSort(steps) {
|
|
25
|
+
const result = this.analyzeDAG(steps);
|
|
26
|
+
if (result.hasCycles) {
|
|
27
|
+
throw new Error(`DAG analysis failed: ${result.errorMessage}`);
|
|
28
|
+
}
|
|
29
|
+
return result.levels;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Analyze DAG structure without throwing
|
|
33
|
+
*
|
|
34
|
+
* @param steps Composite steps to analyze
|
|
35
|
+
* @returns Analysis result with levels or error info
|
|
36
|
+
*/
|
|
37
|
+
static analyzeDAG(steps) {
|
|
38
|
+
// Build dependency graph and in-degree map
|
|
39
|
+
const graph = new Map(); // node -> list of dependent nodes
|
|
40
|
+
const inDegree = new Map();
|
|
41
|
+
// Initialize all nodes
|
|
42
|
+
for (const step of steps) {
|
|
43
|
+
const node = step.store_as;
|
|
44
|
+
inDegree.set(node, 0);
|
|
45
|
+
if (!graph.has(node)) {
|
|
46
|
+
graph.set(node, []);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Build edges and calculate in-degrees
|
|
50
|
+
for (const step of steps) {
|
|
51
|
+
if (step.depends_on) {
|
|
52
|
+
for (const dep of step.depends_on) {
|
|
53
|
+
// Validate dependency exists
|
|
54
|
+
if (!inDegree.has(dep)) {
|
|
55
|
+
return {
|
|
56
|
+
levels: [],
|
|
57
|
+
hasCycles: true,
|
|
58
|
+
errorMessage: `Step '${step.store_as}' depends on '${dep}' but no step produces '${dep}'`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Add edge: dep -> step.store_as
|
|
62
|
+
if (!graph.has(dep)) {
|
|
63
|
+
graph.set(dep, []);
|
|
64
|
+
}
|
|
65
|
+
graph.get(dep).push(step.store_as);
|
|
66
|
+
// Increase in-degree of dependent step
|
|
67
|
+
inDegree.set(step.store_as, inDegree.get(step.store_as) + 1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Kahn's algorithm: BFS with in-degree
|
|
72
|
+
const levels = [];
|
|
73
|
+
const queue = [];
|
|
74
|
+
// Start with nodes having in-degree 0 (no dependencies)
|
|
75
|
+
for (const [node, degree] of inDegree) {
|
|
76
|
+
if (degree === 0) {
|
|
77
|
+
queue.push(node);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Process queue level by level
|
|
81
|
+
while (queue.length > 0) {
|
|
82
|
+
const currentLevel = [];
|
|
83
|
+
const currentIndices = [];
|
|
84
|
+
const levelSize = queue.length;
|
|
85
|
+
// Process all nodes at current level (can run in parallel)
|
|
86
|
+
for (let i = 0; i < levelSize; i++) {
|
|
87
|
+
const node = queue.shift();
|
|
88
|
+
// Find corresponding step and add to level
|
|
89
|
+
const stepIndex = steps.findIndex(s => s.store_as === node);
|
|
90
|
+
if (stepIndex >= 0) {
|
|
91
|
+
currentLevel.push(steps[stepIndex]);
|
|
92
|
+
currentIndices.push(stepIndex);
|
|
93
|
+
}
|
|
94
|
+
// Decrease in-degree of all dependent nodes
|
|
95
|
+
const neighbors = graph.get(node) || [];
|
|
96
|
+
for (const neighbor of neighbors) {
|
|
97
|
+
const newDegree = inDegree.get(neighbor) - 1;
|
|
98
|
+
inDegree.set(neighbor, newDegree);
|
|
99
|
+
// If in-degree becomes 0, add to next level
|
|
100
|
+
if (newDegree === 0) {
|
|
101
|
+
queue.push(neighbor);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Add level if it contains steps
|
|
106
|
+
if (currentLevel.length > 0) {
|
|
107
|
+
levels.push({ steps: currentLevel, stepIndices: currentIndices });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Check for cycles: if not all nodes were processed
|
|
111
|
+
const processedCount = levels.reduce((sum, level) => sum + level.steps.length, 0);
|
|
112
|
+
if (processedCount !== steps.length) {
|
|
113
|
+
// Find unprocessed nodes (part of cycle)
|
|
114
|
+
const processedNodes = new Set();
|
|
115
|
+
for (const level of levels) {
|
|
116
|
+
for (const step of level.steps) {
|
|
117
|
+
processedNodes.add(step.store_as);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const cycleNodes = [];
|
|
121
|
+
for (const step of steps) {
|
|
122
|
+
if (!processedNodes.has(step.store_as)) {
|
|
123
|
+
cycleNodes.push(step.store_as);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
levels: [],
|
|
128
|
+
hasCycles: true,
|
|
129
|
+
errorMessage: `Circular dependency detected involving: ${cycleNodes.join(', ')}`
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
levels,
|
|
134
|
+
hasCycles: false
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=dag-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-executor.js","sourceRoot":"","sources":["../../../src/tooling/dag-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAqBH;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACtB;;;;;;OAMG;IACH,MAAM,CAAC,eAAe,CAAC,KAAsB;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,KAAsB;QACtC,2CAA2C;QAC3C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC,CAAC,kCAAkC;QAC7E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE3C,uBAAuB;QACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC3B,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QAED,uCAAuC;QACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBAClC,6BAA6B;oBAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wBACvB,OAAO;4BACL,MAAM,EAAE,EAAE;4BACV,SAAS,EAAE,IAAI;4BACf,YAAY,EAAE,SAAS,IAAI,CAAC,QAAQ,iBAAiB,GAAG,2BAA2B,GAAG,GAAG;yBAC1F,CAAC;oBACJ,CAAC;oBAED,iCAAiC;oBACjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wBACpB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;oBACrB,CAAC;oBACD,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAEpC,uCAAuC;oBACvC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAE,GAAG,CAAC,CAAC,CAAC;gBAChE,CAAC;YACH,CAAC;QACH,CAAC;QAED,uCAAuC;QACvC,MAAM,MAAM,GAAqB,EAAE,CAAC;QACpC,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,wDAAwD;QACxD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACtC,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,YAAY,GAAoB,EAAE,CAAC;YACzC,MAAM,cAAc,GAAa,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;YAE/B,2DAA2D;YAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;gBAE5B,2CAA2C;gBAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;gBAC5D,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;oBACnB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;oBACpC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACjC,CAAC;gBAED,4CAA4C;gBAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACxC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;oBACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAE,GAAG,CAAC,CAAC;oBAC9C,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;oBAElC,4CAA4C;oBAC5C,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;wBACpB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACvB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,iCAAiC;YACjC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QAED,oDAAoD;QACpD,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAClF,IAAI,cAAc,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;YACpC,yCAAyC;YACzC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;YACzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAC/B,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;YAED,MAAM,UAAU,GAAa,EAAE,CAAC;YAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;YAED,OAAO;gBACL,MAAM,EAAE,EAAE;gBACV,SAAS,EAAE,IAAI;gBACf,YAAY,EAAE,2CAA2C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACjF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM;YACN,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proxy download executor for fetching binary content through API
|
|
3
|
+
*
|
|
4
|
+
* Why: LLM needs file content but URLs require authentication.
|
|
5
|
+
* This executor fetches metadata, extracts URL, downloads content,
|
|
6
|
+
* and returns base64-encoded result.
|
|
7
|
+
*/
|
|
8
|
+
import type { ProxyDownloadOperation } from '../types/profile.js';
|
|
9
|
+
import type { ResponseContext, AuthCredentials } from '../transport/interceptors.js';
|
|
10
|
+
export interface DebugLogger {
|
|
11
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
12
|
+
warn?(message: string, context?: Record<string, unknown>): void;
|
|
13
|
+
}
|
|
14
|
+
export interface HttpClient {
|
|
15
|
+
request(method: string, url: string, options?: {
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
body?: unknown;
|
|
18
|
+
}): Promise<ResponseContext>;
|
|
19
|
+
getBaseUrl(): string;
|
|
20
|
+
}
|
|
21
|
+
export interface ProxyDownloadResult {
|
|
22
|
+
/** Original metadata from API */
|
|
23
|
+
metadata: Record<string, unknown>;
|
|
24
|
+
/** Base64-encoded file content */
|
|
25
|
+
content: string;
|
|
26
|
+
/** MIME type of the file */
|
|
27
|
+
mimeType: string;
|
|
28
|
+
/** File size in bytes */
|
|
29
|
+
size: number;
|
|
30
|
+
/** Original filename if available */
|
|
31
|
+
fileName?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare class ProxyDownloadExecutor {
|
|
34
|
+
private httpClient;
|
|
35
|
+
private logger;
|
|
36
|
+
constructor(httpClient: HttpClient, logger?: DebugLogger);
|
|
37
|
+
/**
|
|
38
|
+
* Execute proxy download operation
|
|
39
|
+
*
|
|
40
|
+
* @param operation Proxy download configuration
|
|
41
|
+
* @param path API path with substituted parameters
|
|
42
|
+
* @param authCredentials Auth credentials (headers + query params) for download
|
|
43
|
+
*/
|
|
44
|
+
execute(operation: ProxyDownloadOperation, metadataRequest: {
|
|
45
|
+
path: string;
|
|
46
|
+
method: string;
|
|
47
|
+
}, authCredentials: AuthCredentials, directDownloadRequest?: {
|
|
48
|
+
path: string;
|
|
49
|
+
method: string;
|
|
50
|
+
}): Promise<ProxyDownloadResult>;
|
|
51
|
+
private resolveMaxSize;
|
|
52
|
+
/**
|
|
53
|
+
* Extract URL from metadata using dot-notation path
|
|
54
|
+
*/
|
|
55
|
+
private extractUrl;
|
|
56
|
+
private extractNestedString;
|
|
57
|
+
private extractNestedNumber;
|
|
58
|
+
private extractNestedValue;
|
|
59
|
+
private getBaseOrigin;
|
|
60
|
+
private resolveHttpUrl;
|
|
61
|
+
private enforceDownloadPolicy;
|
|
62
|
+
/**
|
|
63
|
+
* Check if MIME type matches whitelist (supports wildcards like 'image/*')
|
|
64
|
+
*/
|
|
65
|
+
private isMimeTypeAllowed;
|
|
66
|
+
/**
|
|
67
|
+
* Download binary content and return base64
|
|
68
|
+
*
|
|
69
|
+
* @param skipAuth If true, download URL is fetched without authentication headers/params
|
|
70
|
+
* Metadata endpoint still requires auth, only the final download is unauthenticated
|
|
71
|
+
*/
|
|
72
|
+
private downloadWithAuth;
|
|
73
|
+
private buildDownloadUrlWithOptionalQueryAuth;
|
|
74
|
+
private isRedirectStatus;
|
|
75
|
+
private resolveRedirectTarget;
|
|
76
|
+
private enforceAllowedDownloadTarget;
|
|
77
|
+
private lookupAllIpAddresses;
|
|
78
|
+
private isAllowedHost;
|
|
79
|
+
private isDisallowedIPv4;
|
|
80
|
+
private isDisallowedIPv6;
|
|
81
|
+
/**
|
|
82
|
+
* Handle inline data URLs (data:mime;base64,...)
|
|
83
|
+
*/
|
|
84
|
+
private downloadFromDataUrl;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=proxy-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-executor.d.ts","sourceRoot":"","sources":["../../../src/tooling/proxy-executor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMrF,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACjE;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CACL,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,GACA,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5B,UAAU,IAAI,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAElC,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAEhB,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IAEjB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IAEb,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,MAAM;gBADN,UAAU,EAAE,UAAU,EACtB,MAAM,GAAE,WAAiC;IAGnD;;;;;;OAMG;IACG,OAAO,CACX,SAAS,EAAE,sBAAsB,EACjC,eAAe,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EACjD,eAAe,EAAE,eAAe,EAChC,qBAAqB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACvD,OAAO,CAAC,mBAAmB,CAAC;IA6H/B,OAAO,CAAC,cAAc;IAyBtB;;OAEG;IACH,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,cAAc;YA6CR,qBAAqB;IAuBnC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;;;;OAKG;YACW,gBAAgB;IAqG9B,OAAO,CAAC,qCAAqC;IAiB7C,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,qBAAqB;YAef,4BAA4B;YAsE5B,oBAAoB;IAkClC,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAa5B"}
|