@dotsetlabs/bellwether 0.10.0
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/CHANGELOG.md +291 -0
- package/LICENSE +21 -0
- package/README.md +739 -0
- package/dist/auth/credentials.d.ts +64 -0
- package/dist/auth/credentials.js +218 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/keychain.d.ts +64 -0
- package/dist/auth/keychain.js +268 -0
- package/dist/baseline/ab-testing.d.ts +80 -0
- package/dist/baseline/ab-testing.js +236 -0
- package/dist/baseline/ai-compatibility-scorer.d.ts +95 -0
- package/dist/baseline/ai-compatibility-scorer.js +606 -0
- package/dist/baseline/calibration.d.ts +77 -0
- package/dist/baseline/calibration.js +136 -0
- package/dist/baseline/category-matching.d.ts +85 -0
- package/dist/baseline/category-matching.js +289 -0
- package/dist/baseline/change-impact-analyzer.d.ts +98 -0
- package/dist/baseline/change-impact-analyzer.js +592 -0
- package/dist/baseline/comparator.d.ts +64 -0
- package/dist/baseline/comparator.js +916 -0
- package/dist/baseline/confidence.d.ts +55 -0
- package/dist/baseline/confidence.js +122 -0
- package/dist/baseline/converter.d.ts +61 -0
- package/dist/baseline/converter.js +585 -0
- package/dist/baseline/dependency-analyzer.d.ts +89 -0
- package/dist/baseline/dependency-analyzer.js +567 -0
- package/dist/baseline/deprecation-tracker.d.ts +133 -0
- package/dist/baseline/deprecation-tracker.js +322 -0
- package/dist/baseline/diff.d.ts +55 -0
- package/dist/baseline/diff.js +1584 -0
- package/dist/baseline/documentation-scorer.d.ts +205 -0
- package/dist/baseline/documentation-scorer.js +466 -0
- package/dist/baseline/embeddings.d.ts +118 -0
- package/dist/baseline/embeddings.js +251 -0
- package/dist/baseline/error-analyzer.d.ts +198 -0
- package/dist/baseline/error-analyzer.js +721 -0
- package/dist/baseline/evaluation/evaluator.d.ts +42 -0
- package/dist/baseline/evaluation/evaluator.js +323 -0
- package/dist/baseline/evaluation/expanded-dataset.d.ts +45 -0
- package/dist/baseline/evaluation/expanded-dataset.js +1164 -0
- package/dist/baseline/evaluation/golden-dataset.d.ts +58 -0
- package/dist/baseline/evaluation/golden-dataset.js +717 -0
- package/dist/baseline/evaluation/index.d.ts +15 -0
- package/dist/baseline/evaluation/index.js +15 -0
- package/dist/baseline/evaluation/types.d.ts +186 -0
- package/dist/baseline/evaluation/types.js +8 -0
- package/dist/baseline/external-dependency-detector.d.ts +181 -0
- package/dist/baseline/external-dependency-detector.js +524 -0
- package/dist/baseline/golden-output.d.ts +162 -0
- package/dist/baseline/golden-output.js +636 -0
- package/dist/baseline/health-scorer.d.ts +174 -0
- package/dist/baseline/health-scorer.js +451 -0
- package/dist/baseline/incremental-checker.d.ts +97 -0
- package/dist/baseline/incremental-checker.js +174 -0
- package/dist/baseline/index.d.ts +31 -0
- package/dist/baseline/index.js +42 -0
- package/dist/baseline/migration-generator.d.ts +137 -0
- package/dist/baseline/migration-generator.js +554 -0
- package/dist/baseline/migrations.d.ts +60 -0
- package/dist/baseline/migrations.js +197 -0
- package/dist/baseline/performance-tracker.d.ts +214 -0
- package/dist/baseline/performance-tracker.js +577 -0
- package/dist/baseline/pr-comment-generator.d.ts +117 -0
- package/dist/baseline/pr-comment-generator.js +546 -0
- package/dist/baseline/response-fingerprint.d.ts +127 -0
- package/dist/baseline/response-fingerprint.js +728 -0
- package/dist/baseline/response-schema-tracker.d.ts +129 -0
- package/dist/baseline/response-schema-tracker.js +420 -0
- package/dist/baseline/risk-scorer.d.ts +54 -0
- package/dist/baseline/risk-scorer.js +434 -0
- package/dist/baseline/saver.d.ts +89 -0
- package/dist/baseline/saver.js +554 -0
- package/dist/baseline/scenario-generator.d.ts +151 -0
- package/dist/baseline/scenario-generator.js +905 -0
- package/dist/baseline/schema-compare.d.ts +86 -0
- package/dist/baseline/schema-compare.js +557 -0
- package/dist/baseline/schema-evolution.d.ts +189 -0
- package/dist/baseline/schema-evolution.js +467 -0
- package/dist/baseline/semantic.d.ts +203 -0
- package/dist/baseline/semantic.js +908 -0
- package/dist/baseline/synonyms.d.ts +60 -0
- package/dist/baseline/synonyms.js +386 -0
- package/dist/baseline/telemetry.d.ts +165 -0
- package/dist/baseline/telemetry.js +294 -0
- package/dist/baseline/test-pruner.d.ts +120 -0
- package/dist/baseline/test-pruner.js +387 -0
- package/dist/baseline/types.d.ts +449 -0
- package/dist/baseline/types.js +5 -0
- package/dist/baseline/version.d.ts +138 -0
- package/dist/baseline/version.js +206 -0
- package/dist/cache/index.d.ts +5 -0
- package/dist/cache/index.js +5 -0
- package/dist/cache/response-cache.d.ts +151 -0
- package/dist/cache/response-cache.js +287 -0
- package/dist/ci/index.d.ts +60 -0
- package/dist/ci/index.js +342 -0
- package/dist/cli/commands/auth.d.ts +12 -0
- package/dist/cli/commands/auth.js +352 -0
- package/dist/cli/commands/badge.d.ts +3 -0
- package/dist/cli/commands/badge.js +74 -0
- package/dist/cli/commands/baseline-accept.d.ts +15 -0
- package/dist/cli/commands/baseline-accept.js +178 -0
- package/dist/cli/commands/baseline-migrate.d.ts +12 -0
- package/dist/cli/commands/baseline-migrate.js +164 -0
- package/dist/cli/commands/baseline.d.ts +14 -0
- package/dist/cli/commands/baseline.js +449 -0
- package/dist/cli/commands/beta.d.ts +10 -0
- package/dist/cli/commands/beta.js +231 -0
- package/dist/cli/commands/check.d.ts +11 -0
- package/dist/cli/commands/check.js +820 -0
- package/dist/cli/commands/cloud/badge.d.ts +3 -0
- package/dist/cli/commands/cloud/badge.js +74 -0
- package/dist/cli/commands/cloud/diff.d.ts +6 -0
- package/dist/cli/commands/cloud/diff.js +79 -0
- package/dist/cli/commands/cloud/history.d.ts +6 -0
- package/dist/cli/commands/cloud/history.js +102 -0
- package/dist/cli/commands/cloud/link.d.ts +9 -0
- package/dist/cli/commands/cloud/link.js +119 -0
- package/dist/cli/commands/cloud/login.d.ts +7 -0
- package/dist/cli/commands/cloud/login.js +499 -0
- package/dist/cli/commands/cloud/projects.d.ts +6 -0
- package/dist/cli/commands/cloud/projects.js +44 -0
- package/dist/cli/commands/cloud/shared.d.ts +7 -0
- package/dist/cli/commands/cloud/shared.js +42 -0
- package/dist/cli/commands/cloud/teams.d.ts +8 -0
- package/dist/cli/commands/cloud/teams.js +169 -0
- package/dist/cli/commands/cloud/upload.d.ts +8 -0
- package/dist/cli/commands/cloud/upload.js +181 -0
- package/dist/cli/commands/contract.d.ts +11 -0
- package/dist/cli/commands/contract.js +280 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.js +82 -0
- package/dist/cli/commands/eval.d.ts +9 -0
- package/dist/cli/commands/eval.js +187 -0
- package/dist/cli/commands/explore.d.ts +11 -0
- package/dist/cli/commands/explore.js +437 -0
- package/dist/cli/commands/feedback.d.ts +9 -0
- package/dist/cli/commands/feedback.js +174 -0
- package/dist/cli/commands/golden.d.ts +12 -0
- package/dist/cli/commands/golden.js +407 -0
- package/dist/cli/commands/history.d.ts +10 -0
- package/dist/cli/commands/history.js +202 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +219 -0
- package/dist/cli/commands/interview.d.ts +3 -0
- package/dist/cli/commands/interview.js +903 -0
- package/dist/cli/commands/link.d.ts +10 -0
- package/dist/cli/commands/link.js +169 -0
- package/dist/cli/commands/login.d.ts +7 -0
- package/dist/cli/commands/login.js +499 -0
- package/dist/cli/commands/preset.d.ts +33 -0
- package/dist/cli/commands/preset.js +297 -0
- package/dist/cli/commands/profile.d.ts +33 -0
- package/dist/cli/commands/profile.js +286 -0
- package/dist/cli/commands/registry.d.ts +11 -0
- package/dist/cli/commands/registry.js +146 -0
- package/dist/cli/commands/shared.d.ts +79 -0
- package/dist/cli/commands/shared.js +196 -0
- package/dist/cli/commands/teams.d.ts +8 -0
- package/dist/cli/commands/teams.js +169 -0
- package/dist/cli/commands/test.d.ts +9 -0
- package/dist/cli/commands/test.js +500 -0
- package/dist/cli/commands/upload.d.ts +8 -0
- package/dist/cli/commands/upload.js +223 -0
- package/dist/cli/commands/validate-config.d.ts +6 -0
- package/dist/cli/commands/validate-config.js +35 -0
- package/dist/cli/commands/verify.d.ts +11 -0
- package/dist/cli/commands/verify.js +283 -0
- package/dist/cli/commands/watch.d.ts +12 -0
- package/dist/cli/commands/watch.js +253 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +178 -0
- package/dist/cli/interactive.d.ts +47 -0
- package/dist/cli/interactive.js +216 -0
- package/dist/cli/output/terminal-reporter.d.ts +19 -0
- package/dist/cli/output/terminal-reporter.js +104 -0
- package/dist/cli/output.d.ts +226 -0
- package/dist/cli/output.js +438 -0
- package/dist/cli/utils/env.d.ts +5 -0
- package/dist/cli/utils/env.js +14 -0
- package/dist/cli/utils/progress.d.ts +59 -0
- package/dist/cli/utils/progress.js +206 -0
- package/dist/cli/utils/server-context.d.ts +10 -0
- package/dist/cli/utils/server-context.js +36 -0
- package/dist/cloud/auth.d.ts +144 -0
- package/dist/cloud/auth.js +374 -0
- package/dist/cloud/client.d.ts +24 -0
- package/dist/cloud/client.js +65 -0
- package/dist/cloud/http-client.d.ts +38 -0
- package/dist/cloud/http-client.js +215 -0
- package/dist/cloud/index.d.ts +23 -0
- package/dist/cloud/index.js +25 -0
- package/dist/cloud/mock-client.d.ts +107 -0
- package/dist/cloud/mock-client.js +545 -0
- package/dist/cloud/types.d.ts +515 -0
- package/dist/cloud/types.js +15 -0
- package/dist/config/defaults.d.ts +160 -0
- package/dist/config/defaults.js +169 -0
- package/dist/config/loader.d.ts +24 -0
- package/dist/config/loader.js +122 -0
- package/dist/config/template.d.ts +42 -0
- package/dist/config/template.js +647 -0
- package/dist/config/validator.d.ts +2112 -0
- package/dist/config/validator.js +658 -0
- package/dist/constants/cloud.d.ts +107 -0
- package/dist/constants/cloud.js +110 -0
- package/dist/constants/core.d.ts +521 -0
- package/dist/constants/core.js +556 -0
- package/dist/constants/testing.d.ts +1283 -0
- package/dist/constants/testing.js +1568 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +10 -0
- package/dist/contract/index.d.ts +6 -0
- package/dist/contract/index.js +5 -0
- package/dist/contract/validator.d.ts +177 -0
- package/dist/contract/validator.js +574 -0
- package/dist/cost/index.d.ts +6 -0
- package/dist/cost/index.js +5 -0
- package/dist/cost/tracker.d.ts +134 -0
- package/dist/cost/tracker.js +313 -0
- package/dist/discovery/discovery.d.ts +16 -0
- package/dist/discovery/discovery.js +173 -0
- package/dist/discovery/types.d.ts +51 -0
- package/dist/discovery/types.js +2 -0
- package/dist/docs/agents.d.ts +3 -0
- package/dist/docs/agents.js +995 -0
- package/dist/docs/contract.d.ts +51 -0
- package/dist/docs/contract.js +1681 -0
- package/dist/docs/generator.d.ts +4 -0
- package/dist/docs/generator.js +4 -0
- package/dist/docs/html-reporter.d.ts +9 -0
- package/dist/docs/html-reporter.js +757 -0
- package/dist/docs/index.d.ts +10 -0
- package/dist/docs/index.js +11 -0
- package/dist/docs/junit-reporter.d.ts +18 -0
- package/dist/docs/junit-reporter.js +210 -0
- package/dist/docs/report.d.ts +14 -0
- package/dist/docs/report.js +44 -0
- package/dist/docs/sarif-reporter.d.ts +19 -0
- package/dist/docs/sarif-reporter.js +335 -0
- package/dist/docs/shared.d.ts +35 -0
- package/dist/docs/shared.js +162 -0
- package/dist/docs/templates.d.ts +12 -0
- package/dist/docs/templates.js +76 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.js +6 -0
- package/dist/errors/retry.d.ts +92 -0
- package/dist/errors/retry.js +323 -0
- package/dist/errors/types.d.ts +321 -0
- package/dist/errors/types.js +584 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +32 -0
- package/dist/interview/dependency-resolver.d.ts +11 -0
- package/dist/interview/dependency-resolver.js +32 -0
- package/dist/interview/interviewer.d.ts +232 -0
- package/dist/interview/interviewer.js +1939 -0
- package/dist/interview/mock-response-generator.d.ts +7 -0
- package/dist/interview/mock-response-generator.js +102 -0
- package/dist/interview/orchestrator.d.ts +237 -0
- package/dist/interview/orchestrator.js +1296 -0
- package/dist/interview/rate-limiter.d.ts +15 -0
- package/dist/interview/rate-limiter.js +55 -0
- package/dist/interview/response-validator.d.ts +10 -0
- package/dist/interview/response-validator.js +132 -0
- package/dist/interview/schema-inferrer.d.ts +8 -0
- package/dist/interview/schema-inferrer.js +71 -0
- package/dist/interview/schema-test-generator.d.ts +71 -0
- package/dist/interview/schema-test-generator.js +834 -0
- package/dist/interview/smart-value-generator.d.ts +155 -0
- package/dist/interview/smart-value-generator.js +554 -0
- package/dist/interview/stateful-test-runner.d.ts +19 -0
- package/dist/interview/stateful-test-runner.js +106 -0
- package/dist/interview/types.d.ts +561 -0
- package/dist/interview/types.js +2 -0
- package/dist/llm/anthropic.d.ts +41 -0
- package/dist/llm/anthropic.js +355 -0
- package/dist/llm/client.d.ts +123 -0
- package/dist/llm/client.js +42 -0
- package/dist/llm/factory.d.ts +38 -0
- package/dist/llm/factory.js +145 -0
- package/dist/llm/fallback.d.ts +140 -0
- package/dist/llm/fallback.js +379 -0
- package/dist/llm/index.d.ts +18 -0
- package/dist/llm/index.js +15 -0
- package/dist/llm/ollama.d.ts +37 -0
- package/dist/llm/ollama.js +330 -0
- package/dist/llm/openai.d.ts +25 -0
- package/dist/llm/openai.js +320 -0
- package/dist/llm/token-budget.d.ts +161 -0
- package/dist/llm/token-budget.js +395 -0
- package/dist/logging/logger.d.ts +70 -0
- package/dist/logging/logger.js +130 -0
- package/dist/metrics/collector.d.ts +106 -0
- package/dist/metrics/collector.js +547 -0
- package/dist/metrics/index.d.ts +7 -0
- package/dist/metrics/index.js +7 -0
- package/dist/metrics/prometheus.d.ts +20 -0
- package/dist/metrics/prometheus.js +241 -0
- package/dist/metrics/types.d.ts +209 -0
- package/dist/metrics/types.js +5 -0
- package/dist/persona/builtins.d.ts +54 -0
- package/dist/persona/builtins.js +219 -0
- package/dist/persona/index.d.ts +8 -0
- package/dist/persona/index.js +8 -0
- package/dist/persona/loader.d.ts +30 -0
- package/dist/persona/loader.js +190 -0
- package/dist/persona/types.d.ts +144 -0
- package/dist/persona/types.js +5 -0
- package/dist/persona/validation.d.ts +94 -0
- package/dist/persona/validation.js +332 -0
- package/dist/prompts/index.d.ts +5 -0
- package/dist/prompts/index.js +5 -0
- package/dist/prompts/templates.d.ts +180 -0
- package/dist/prompts/templates.js +431 -0
- package/dist/registry/client.d.ts +49 -0
- package/dist/registry/client.js +191 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +6 -0
- package/dist/registry/types.d.ts +140 -0
- package/dist/registry/types.js +6 -0
- package/dist/scenarios/evaluator.d.ts +43 -0
- package/dist/scenarios/evaluator.js +206 -0
- package/dist/scenarios/index.d.ts +10 -0
- package/dist/scenarios/index.js +9 -0
- package/dist/scenarios/loader.d.ts +20 -0
- package/dist/scenarios/loader.js +285 -0
- package/dist/scenarios/types.d.ts +153 -0
- package/dist/scenarios/types.js +8 -0
- package/dist/security/index.d.ts +17 -0
- package/dist/security/index.js +18 -0
- package/dist/security/payloads.d.ts +61 -0
- package/dist/security/payloads.js +268 -0
- package/dist/security/security-tester.d.ts +42 -0
- package/dist/security/security-tester.js +582 -0
- package/dist/security/types.d.ts +166 -0
- package/dist/security/types.js +8 -0
- package/dist/transport/base-transport.d.ts +59 -0
- package/dist/transport/base-transport.js +38 -0
- package/dist/transport/http-transport.d.ts +67 -0
- package/dist/transport/http-transport.js +238 -0
- package/dist/transport/mcp-client.d.ts +141 -0
- package/dist/transport/mcp-client.js +496 -0
- package/dist/transport/sse-transport.d.ts +88 -0
- package/dist/transport/sse-transport.js +316 -0
- package/dist/transport/stdio-transport.d.ts +43 -0
- package/dist/transport/stdio-transport.js +238 -0
- package/dist/transport/types.d.ts +125 -0
- package/dist/transport/types.js +16 -0
- package/dist/utils/concurrency.d.ts +123 -0
- package/dist/utils/concurrency.js +213 -0
- package/dist/utils/formatters.d.ts +16 -0
- package/dist/utils/formatters.js +37 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/jsonpath.d.ts +87 -0
- package/dist/utils/jsonpath.js +326 -0
- package/dist/utils/markdown.d.ts +113 -0
- package/dist/utils/markdown.js +265 -0
- package/dist/utils/network.d.ts +14 -0
- package/dist/utils/network.js +17 -0
- package/dist/utils/sanitize.d.ts +92 -0
- package/dist/utils/sanitize.js +191 -0
- package/dist/utils/semantic.d.ts +194 -0
- package/dist/utils/semantic.js +1051 -0
- package/dist/utils/smart-truncate.d.ts +94 -0
- package/dist/utils/smart-truncate.js +361 -0
- package/dist/utils/timeout.d.ts +153 -0
- package/dist/utils/timeout.js +205 -0
- package/dist/utils/yaml-parser.d.ts +58 -0
- package/dist/utils/yaml-parser.js +86 -0
- package/dist/validation/index.d.ts +32 -0
- package/dist/validation/index.js +32 -0
- package/dist/validation/semantic-test-generator.d.ts +50 -0
- package/dist/validation/semantic-test-generator.js +176 -0
- package/dist/validation/semantic-types.d.ts +66 -0
- package/dist/validation/semantic-types.js +94 -0
- package/dist/validation/semantic-validator.d.ts +38 -0
- package/dist/validation/semantic-validator.js +340 -0
- package/dist/verification/index.d.ts +6 -0
- package/dist/verification/index.js +5 -0
- package/dist/verification/types.d.ts +133 -0
- package/dist/verification/types.js +5 -0
- package/dist/verification/verifier.d.ts +30 -0
- package/dist/verification/verifier.js +309 -0
- package/dist/version.d.ts +19 -0
- package/dist/version.js +48 -0
- package/dist/workflow/auto-generator.d.ts +27 -0
- package/dist/workflow/auto-generator.js +513 -0
- package/dist/workflow/discovery.d.ts +40 -0
- package/dist/workflow/discovery.js +195 -0
- package/dist/workflow/executor.d.ts +82 -0
- package/dist/workflow/executor.js +611 -0
- package/dist/workflow/index.d.ts +10 -0
- package/dist/workflow/index.js +10 -0
- package/dist/workflow/loader.d.ts +24 -0
- package/dist/workflow/loader.js +194 -0
- package/dist/workflow/state-tracker.d.ts +98 -0
- package/dist/workflow/state-tracker.js +424 -0
- package/dist/workflow/types.d.ts +337 -0
- package/dist/workflow/types.js +5 -0
- package/package.json +94 -0
- package/schemas/bellwether-check.schema.json +651 -0
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-Tool Dependency Analyzer.
|
|
3
|
+
*
|
|
4
|
+
* Analyzes tool descriptions and schemas to identify dependencies
|
|
5
|
+
* between tools, enabling better testing strategies and documentation.
|
|
6
|
+
*
|
|
7
|
+
* Detection strategies:
|
|
8
|
+
* 1. Description analysis - mentions of other tool names
|
|
9
|
+
* 2. Parameter name matching - params that match output field names
|
|
10
|
+
* 3. Resource reference patterns - common ID/token patterns
|
|
11
|
+
* 4. Workflow step order - sequence implied by tool naming
|
|
12
|
+
*/
|
|
13
|
+
import { mermaidLabel } from '../utils/index.js';
|
|
14
|
+
// Common patterns for tool relationships
|
|
15
|
+
const DEPENDENCY_PATTERNS = [
|
|
16
|
+
// "requires output from X" / "requires X"
|
|
17
|
+
{ pattern: /requires?\s+(?:output\s+from\s+)?['"`]?(\w+)['"`]?/gi, type: 'mention' },
|
|
18
|
+
// "after calling X" / "after X"
|
|
19
|
+
{ pattern: /after\s+(?:calling\s+)?['"`]?(\w+)['"`]?/gi, type: 'sequence' },
|
|
20
|
+
// "use result from X" / "use output of X"
|
|
21
|
+
{ pattern: /use\s+(?:the\s+)?(?:result|output)\s+(?:of|from)\s+['"`]?(\w+)['"`]?/gi, type: 'output_input' },
|
|
22
|
+
// "first call X" / "call X first"
|
|
23
|
+
{ pattern: /(?:first\s+call|call\s+first)\s+['"`]?(\w+)['"`]?/gi, type: 'sequence' },
|
|
24
|
+
// "chain with X" / "chains to X"
|
|
25
|
+
{ pattern: /chains?\s+(?:with|to)\s+['"`]?(\w+)['"`]?/gi, type: 'sequence' },
|
|
26
|
+
// "needs X" / "need X to"
|
|
27
|
+
{ pattern: /needs?\s+['"`]?(\w+)['"`]?\s+(?:to|first)?/gi, type: 'mention' },
|
|
28
|
+
// "X returns ... which is used by"
|
|
29
|
+
{ pattern: /['"`]?(\w+)['"`]?\s+returns?.*which\s+is\s+used/gi, type: 'output_input' },
|
|
30
|
+
];
|
|
31
|
+
// Common ID/token parameter patterns that suggest dependencies
|
|
32
|
+
const ID_PARAMETER_PATTERNS = [
|
|
33
|
+
{ pattern: /^(item|access|session|auth|link|public)_?token$/i, prefix: 'link' },
|
|
34
|
+
{ pattern: /^(item|account|user|resource|entity)_?id$/i, prefix: '' },
|
|
35
|
+
{ pattern: /^(cursor|next_?cursor|page_?token)$/i, prefix: '' },
|
|
36
|
+
{ pattern: /^(file|resource)_?path$/i, prefix: '' },
|
|
37
|
+
];
|
|
38
|
+
// Common output field names that create resources
|
|
39
|
+
// Note: Reserved for future enhanced dependency detection
|
|
40
|
+
const _RESOURCE_OUTPUT_PATTERNS = [
|
|
41
|
+
'id', 'item_id', 'account_id', 'user_id', 'token', 'link_token',
|
|
42
|
+
'access_token', 'session_id', 'path', 'file_path', 'resource_id',
|
|
43
|
+
];
|
|
44
|
+
void _RESOURCE_OUTPUT_PATTERNS;
|
|
45
|
+
/**
|
|
46
|
+
* Analyze dependencies between tools.
|
|
47
|
+
*/
|
|
48
|
+
export function analyzeDependencies(tools) {
|
|
49
|
+
const edges = [];
|
|
50
|
+
const toolNames = new Set(tools.map(t => t.name.toLowerCase()));
|
|
51
|
+
const toolMap = new Map(tools.map(t => [t.name.toLowerCase(), t]));
|
|
52
|
+
for (const tool of tools) {
|
|
53
|
+
// Strategy 1: Description analysis
|
|
54
|
+
const mentionEdges = extractToolMentions(tool, tools, toolNames);
|
|
55
|
+
edges.push(...mentionEdges);
|
|
56
|
+
// Strategy 2: Parameter name matching
|
|
57
|
+
const paramEdges = findParameterMatches(tool, tools);
|
|
58
|
+
edges.push(...paramEdges);
|
|
59
|
+
// Strategy 3: Resource reference patterns
|
|
60
|
+
const resourceEdges = findResourceReferences(tool, tools, toolMap);
|
|
61
|
+
edges.push(...resourceEdges);
|
|
62
|
+
// Strategy 4: Sequence patterns from naming
|
|
63
|
+
const sequenceEdges = findSequencePatterns(tool, tools, toolNames);
|
|
64
|
+
edges.push(...sequenceEdges);
|
|
65
|
+
}
|
|
66
|
+
// Deduplicate edges (keep highest confidence for each pair)
|
|
67
|
+
const deduped = deduplicateEdges(edges);
|
|
68
|
+
// Build graph structure
|
|
69
|
+
return buildGraph(deduped, tools);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract tool mentions from a tool's description.
|
|
73
|
+
*/
|
|
74
|
+
function extractToolMentions(tool, allTools, toolNames) {
|
|
75
|
+
const edges = [];
|
|
76
|
+
const description = tool.description || '';
|
|
77
|
+
// Check explicit patterns
|
|
78
|
+
for (const { pattern, type } of DEPENDENCY_PATTERNS) {
|
|
79
|
+
let match;
|
|
80
|
+
while ((match = pattern.exec(description)) !== null) {
|
|
81
|
+
const mentionedTool = match[1].toLowerCase();
|
|
82
|
+
if (toolNames.has(mentionedTool) && mentionedTool !== tool.name.toLowerCase()) {
|
|
83
|
+
edges.push({
|
|
84
|
+
from: mentionedTool,
|
|
85
|
+
to: tool.name,
|
|
86
|
+
type,
|
|
87
|
+
confidence: 0.9,
|
|
88
|
+
description: `${tool.name} description mentions ${mentionedTool}`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Check for direct tool name mentions
|
|
94
|
+
for (const otherTool of allTools) {
|
|
95
|
+
if (otherTool.name === tool.name)
|
|
96
|
+
continue;
|
|
97
|
+
const nameVariants = [
|
|
98
|
+
otherTool.name,
|
|
99
|
+
otherTool.name.replace(/_/g, ' '),
|
|
100
|
+
otherTool.name.replace(/_/g, '-'),
|
|
101
|
+
];
|
|
102
|
+
for (const variant of nameVariants) {
|
|
103
|
+
if (description.toLowerCase().includes(variant.toLowerCase())) {
|
|
104
|
+
// Check if already found via pattern
|
|
105
|
+
const existingEdge = edges.find(e => e.from === otherTool.name.toLowerCase() || e.from === otherTool.name);
|
|
106
|
+
if (!existingEdge) {
|
|
107
|
+
edges.push({
|
|
108
|
+
from: otherTool.name,
|
|
109
|
+
to: tool.name,
|
|
110
|
+
type: 'mention',
|
|
111
|
+
confidence: 0.6,
|
|
112
|
+
description: `${tool.name} description mentions ${otherTool.name}`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return edges;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Find dependencies based on parameter name matching.
|
|
122
|
+
*/
|
|
123
|
+
function findParameterMatches(tool, allTools) {
|
|
124
|
+
const edges = [];
|
|
125
|
+
const schema = tool.inputSchema;
|
|
126
|
+
if (!schema?.properties)
|
|
127
|
+
return edges;
|
|
128
|
+
const params = Object.keys(schema.properties);
|
|
129
|
+
for (const param of params) {
|
|
130
|
+
// Check if this param matches known ID/token patterns
|
|
131
|
+
for (const { pattern, prefix } of ID_PARAMETER_PATTERNS) {
|
|
132
|
+
if (!pattern.test(param))
|
|
133
|
+
continue;
|
|
134
|
+
// Look for tools that might produce this
|
|
135
|
+
for (const otherTool of allTools) {
|
|
136
|
+
if (otherTool.name === tool.name)
|
|
137
|
+
continue;
|
|
138
|
+
// Check if other tool name suggests it produces this type of output
|
|
139
|
+
const otherName = otherTool.name.toLowerCase();
|
|
140
|
+
const paramLower = param.toLowerCase();
|
|
141
|
+
// E.g., param "item_id" might come from "get_item", "create_item", "link_exchange"
|
|
142
|
+
const resourceType = paramLower.replace(/_?(id|token)$/i, '');
|
|
143
|
+
if (otherName.includes(resourceType) ||
|
|
144
|
+
(prefix && otherName.includes(prefix)) ||
|
|
145
|
+
otherName.includes('create') ||
|
|
146
|
+
otherName.includes('link') ||
|
|
147
|
+
otherName.includes('exchange')) {
|
|
148
|
+
edges.push({
|
|
149
|
+
from: otherTool.name,
|
|
150
|
+
to: tool.name,
|
|
151
|
+
type: 'output_input',
|
|
152
|
+
confidence: 0.5,
|
|
153
|
+
description: `${tool.name}.${param} may use output from ${otherTool.name}`,
|
|
154
|
+
field: param,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return edges;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Find resource reference patterns.
|
|
164
|
+
*/
|
|
165
|
+
function findResourceReferences(tool, allTools, _toolMap) {
|
|
166
|
+
const edges = [];
|
|
167
|
+
const toolName = tool.name.toLowerCase();
|
|
168
|
+
// Extract resource type from tool name
|
|
169
|
+
const resourceMatch = toolName.match(/(?:get|list|update|delete|search|find)_?(\w+)/);
|
|
170
|
+
if (!resourceMatch)
|
|
171
|
+
return edges;
|
|
172
|
+
const resourceType = resourceMatch[1];
|
|
173
|
+
// Look for create/link tools for this resource
|
|
174
|
+
for (const otherTool of allTools) {
|
|
175
|
+
if (otherTool.name === tool.name)
|
|
176
|
+
continue;
|
|
177
|
+
const otherName = otherTool.name.toLowerCase();
|
|
178
|
+
// create_X -> [get|list|update|delete]_X dependency
|
|
179
|
+
if (otherName.includes(resourceType) &&
|
|
180
|
+
(otherName.includes('create') || otherName.includes('add') ||
|
|
181
|
+
otherName.includes('link') || otherName.includes('exchange'))) {
|
|
182
|
+
edges.push({
|
|
183
|
+
from: otherTool.name,
|
|
184
|
+
to: tool.name,
|
|
185
|
+
type: 'resource_ref',
|
|
186
|
+
confidence: 0.7,
|
|
187
|
+
description: `${otherTool.name} creates ${resourceType} used by ${tool.name}`,
|
|
188
|
+
field: resourceType,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return edges;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Find sequence patterns from tool naming conventions.
|
|
196
|
+
*/
|
|
197
|
+
function findSequencePatterns(tool, _allTools, toolNames) {
|
|
198
|
+
const edges = [];
|
|
199
|
+
const toolName = tool.name.toLowerCase();
|
|
200
|
+
// Common sequence patterns
|
|
201
|
+
const sequences = [
|
|
202
|
+
{ suffix: '_sync', precedent: '_link', confidence: 0.6 },
|
|
203
|
+
{ suffix: '_sync', precedent: '_exchange', confidence: 0.6 },
|
|
204
|
+
{ suffix: '_list', precedent: '_sync', confidence: 0.5 },
|
|
205
|
+
{ suffix: '_search', precedent: '_sync', confidence: 0.5 },
|
|
206
|
+
{ suffix: '_details', precedent: '_list', confidence: 0.5 },
|
|
207
|
+
{ suffix: '_update', precedent: '_get', confidence: 0.4 },
|
|
208
|
+
{ suffix: '_delete', precedent: '_get', confidence: 0.4 },
|
|
209
|
+
{ prefix: 'get_', precedent: 'create_', confidence: 0.5 },
|
|
210
|
+
{ prefix: 'list_', precedent: 'create_', confidence: 0.5 },
|
|
211
|
+
{ prefix: 'update_', precedent: 'create_', confidence: 0.5 },
|
|
212
|
+
];
|
|
213
|
+
for (const { suffix, prefix, precedent, confidence } of sequences) {
|
|
214
|
+
// Check if current tool matches the suffix/prefix pattern
|
|
215
|
+
let resourcePart = '';
|
|
216
|
+
if (suffix && toolName.endsWith(suffix)) {
|
|
217
|
+
resourcePart = toolName.slice(0, -suffix.length);
|
|
218
|
+
}
|
|
219
|
+
else if (prefix && toolName.startsWith(prefix)) {
|
|
220
|
+
resourcePart = toolName.slice(prefix.length);
|
|
221
|
+
}
|
|
222
|
+
if (!resourcePart)
|
|
223
|
+
continue;
|
|
224
|
+
// Look for the precedent tool
|
|
225
|
+
const precedentName = precedent.startsWith('_')
|
|
226
|
+
? resourcePart + precedent
|
|
227
|
+
: precedent + resourcePart;
|
|
228
|
+
if (toolNames.has(precedentName)) {
|
|
229
|
+
edges.push({
|
|
230
|
+
from: precedentName,
|
|
231
|
+
to: tool.name,
|
|
232
|
+
type: 'sequence',
|
|
233
|
+
confidence,
|
|
234
|
+
description: `${precedentName} typically runs before ${tool.name}`,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return edges;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Deduplicate edges, keeping highest confidence for each pair.
|
|
242
|
+
*/
|
|
243
|
+
function deduplicateEdges(edges) {
|
|
244
|
+
const edgeMap = new Map();
|
|
245
|
+
for (const edge of edges) {
|
|
246
|
+
const key = `${edge.from}->${edge.to}`;
|
|
247
|
+
const existing = edgeMap.get(key);
|
|
248
|
+
if (!existing || edge.confidence > existing.confidence) {
|
|
249
|
+
edgeMap.set(key, edge);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return Array.from(edgeMap.values());
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Build the full dependency graph from edges.
|
|
256
|
+
*/
|
|
257
|
+
function buildGraph(edges, tools) {
|
|
258
|
+
const toolNames = tools.map(t => t.name);
|
|
259
|
+
// Build adjacency lists
|
|
260
|
+
const dependsOn = new Map();
|
|
261
|
+
const dependedBy = new Map();
|
|
262
|
+
for (const name of toolNames) {
|
|
263
|
+
dependsOn.set(name, new Set());
|
|
264
|
+
dependedBy.set(name, new Set());
|
|
265
|
+
}
|
|
266
|
+
for (const edge of edges) {
|
|
267
|
+
dependsOn.get(edge.to)?.add(edge.from);
|
|
268
|
+
dependedBy.get(edge.from)?.add(edge.to);
|
|
269
|
+
}
|
|
270
|
+
// Find entry points (no dependencies)
|
|
271
|
+
const entryPoints = toolNames.filter(name => (dependsOn.get(name)?.size ?? 0) === 0);
|
|
272
|
+
// Find terminal points (no dependents)
|
|
273
|
+
const terminalPoints = toolNames.filter(name => (dependedBy.get(name)?.size ?? 0) === 0);
|
|
274
|
+
// Build layers using topological sort
|
|
275
|
+
const layers = topologicalLayers(toolNames, dependsOn);
|
|
276
|
+
// Detect cycles
|
|
277
|
+
const cycles = detectCycles(toolNames, dependsOn);
|
|
278
|
+
return {
|
|
279
|
+
edges,
|
|
280
|
+
layers,
|
|
281
|
+
entryPoints,
|
|
282
|
+
terminalPoints,
|
|
283
|
+
cycles,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Build layers using topological sort (tools with same depth in same layer).
|
|
288
|
+
*/
|
|
289
|
+
function topologicalLayers(toolNames, dependsOn) {
|
|
290
|
+
const layers = [];
|
|
291
|
+
const depth = new Map();
|
|
292
|
+
// Initialize depths
|
|
293
|
+
for (const name of toolNames) {
|
|
294
|
+
depth.set(name, 0);
|
|
295
|
+
}
|
|
296
|
+
// Calculate depths iteratively
|
|
297
|
+
let changed = true;
|
|
298
|
+
let iterations = 0;
|
|
299
|
+
const maxIterations = toolNames.length * 2; // Prevent infinite loops
|
|
300
|
+
while (changed && iterations < maxIterations) {
|
|
301
|
+
changed = false;
|
|
302
|
+
iterations++;
|
|
303
|
+
for (const name of toolNames) {
|
|
304
|
+
const deps = dependsOn.get(name) ?? new Set();
|
|
305
|
+
let maxDepDepth = -1;
|
|
306
|
+
for (const dep of deps) {
|
|
307
|
+
const depDepth = depth.get(dep) ?? 0;
|
|
308
|
+
if (depDepth > maxDepDepth) {
|
|
309
|
+
maxDepDepth = depDepth;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const newDepth = maxDepDepth + 1;
|
|
313
|
+
if (newDepth > (depth.get(name) ?? 0)) {
|
|
314
|
+
depth.set(name, newDepth);
|
|
315
|
+
changed = true;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// Group by depth
|
|
320
|
+
const maxDepth = Math.max(...Array.from(depth.values()));
|
|
321
|
+
for (let d = 0; d <= maxDepth; d++) {
|
|
322
|
+
const layerTools = toolNames.filter(name => depth.get(name) === d);
|
|
323
|
+
if (layerTools.length > 0) {
|
|
324
|
+
layers.push(layerTools);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return layers;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Detect cycles in the dependency graph.
|
|
331
|
+
*/
|
|
332
|
+
function detectCycles(toolNames, dependsOn) {
|
|
333
|
+
const cycles = [];
|
|
334
|
+
const visited = new Set();
|
|
335
|
+
const recursionStack = new Set();
|
|
336
|
+
function dfs(node, path) {
|
|
337
|
+
if (recursionStack.has(node)) {
|
|
338
|
+
// Found a cycle
|
|
339
|
+
const cycleStart = path.indexOf(node);
|
|
340
|
+
const cycle = path.slice(cycleStart);
|
|
341
|
+
cycle.push(node);
|
|
342
|
+
cycles.push(cycle);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
if (visited.has(node))
|
|
346
|
+
return;
|
|
347
|
+
visited.add(node);
|
|
348
|
+
recursionStack.add(node);
|
|
349
|
+
path.push(node);
|
|
350
|
+
const deps = dependsOn.get(node) ?? new Set();
|
|
351
|
+
for (const dep of deps) {
|
|
352
|
+
dfs(dep, [...path]);
|
|
353
|
+
}
|
|
354
|
+
recursionStack.delete(node);
|
|
355
|
+
}
|
|
356
|
+
for (const name of toolNames) {
|
|
357
|
+
if (!visited.has(name)) {
|
|
358
|
+
dfs(name, []);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return cycles;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Calculate statistics about the dependency graph.
|
|
365
|
+
*/
|
|
366
|
+
export function calculateDependencyStats(graph) {
|
|
367
|
+
const byType = {
|
|
368
|
+
mention: 0,
|
|
369
|
+
output_input: 0,
|
|
370
|
+
resource_ref: 0,
|
|
371
|
+
sequence: 0,
|
|
372
|
+
shared_resource: 0,
|
|
373
|
+
};
|
|
374
|
+
for (const edge of graph.edges) {
|
|
375
|
+
byType[edge.type]++;
|
|
376
|
+
}
|
|
377
|
+
// Count dependencies per tool
|
|
378
|
+
const depCounts = new Map();
|
|
379
|
+
const depOnCounts = new Map();
|
|
380
|
+
for (const edge of graph.edges) {
|
|
381
|
+
depCounts.set(edge.to, (depCounts.get(edge.to) ?? 0) + 1);
|
|
382
|
+
depOnCounts.set(edge.from, (depOnCounts.get(edge.from) ?? 0) + 1);
|
|
383
|
+
}
|
|
384
|
+
const mostDependent = Array.from(depCounts.entries())
|
|
385
|
+
.map(([tool, count]) => ({ tool, count }))
|
|
386
|
+
.sort((a, b) => b.count - a.count)
|
|
387
|
+
.slice(0, 5);
|
|
388
|
+
const mostDependedUpon = Array.from(depOnCounts.entries())
|
|
389
|
+
.map(([tool, count]) => ({ tool, count }))
|
|
390
|
+
.sort((a, b) => b.count - a.count)
|
|
391
|
+
.slice(0, 5);
|
|
392
|
+
const totalTools = new Set([
|
|
393
|
+
...graph.edges.map(e => e.from),
|
|
394
|
+
...graph.edges.map(e => e.to),
|
|
395
|
+
]).size;
|
|
396
|
+
return {
|
|
397
|
+
totalEdges: graph.edges.length,
|
|
398
|
+
byType,
|
|
399
|
+
avgDependencies: totalTools > 0 ? graph.edges.length / totalTools : 0,
|
|
400
|
+
maxChainLength: graph.layers.length,
|
|
401
|
+
mostDependent,
|
|
402
|
+
mostDependedUpon,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Generate a Mermaid diagram for the dependency graph.
|
|
407
|
+
*/
|
|
408
|
+
export function generateDependencyMermaid(graph) {
|
|
409
|
+
const lines = ['graph TD'];
|
|
410
|
+
// Group edges by confidence for styling
|
|
411
|
+
const highConfidence = graph.edges.filter(e => e.confidence >= 0.7);
|
|
412
|
+
const mediumConfidence = graph.edges.filter(e => e.confidence >= 0.5 && e.confidence < 0.7);
|
|
413
|
+
const lowConfidence = graph.edges.filter(e => e.confidence < 0.5);
|
|
414
|
+
// Add high confidence edges (solid lines)
|
|
415
|
+
for (const edge of highConfidence) {
|
|
416
|
+
const fromLabel = mermaidLabel(edge.from);
|
|
417
|
+
const toLabel = mermaidLabel(edge.to);
|
|
418
|
+
lines.push(` ${fromLabel} --> ${toLabel}`);
|
|
419
|
+
}
|
|
420
|
+
// Add medium confidence edges (dashed lines)
|
|
421
|
+
for (const edge of mediumConfidence) {
|
|
422
|
+
const fromLabel = mermaidLabel(edge.from);
|
|
423
|
+
const toLabel = mermaidLabel(edge.to);
|
|
424
|
+
lines.push(` ${fromLabel} -.-> ${toLabel}`);
|
|
425
|
+
}
|
|
426
|
+
// Add low confidence edges (dotted, if any)
|
|
427
|
+
if (lowConfidence.length > 0 && lowConfidence.length <= 10) {
|
|
428
|
+
for (const edge of lowConfidence) {
|
|
429
|
+
const fromLabel = mermaidLabel(edge.from);
|
|
430
|
+
const toLabel = mermaidLabel(edge.to);
|
|
431
|
+
lines.push(` ${fromLabel} -..-> ${toLabel}`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// Track styled nodes to prevent duplicates (a node can be both entry and terminal)
|
|
435
|
+
const styledNodes = new Set();
|
|
436
|
+
// Add styling for entry points (green - tools that others depend on)
|
|
437
|
+
if (graph.entryPoints.length > 0) {
|
|
438
|
+
for (const entry of graph.entryPoints.slice(0, 10)) {
|
|
439
|
+
const label = mermaidLabel(entry);
|
|
440
|
+
if (!styledNodes.has(label)) {
|
|
441
|
+
lines.push(` style ${label} fill:#90EE90`);
|
|
442
|
+
styledNodes.add(label);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// Add styling for terminal points (pink - tools that depend on others)
|
|
447
|
+
// Skip if already styled as entry point to avoid duplicate declarations
|
|
448
|
+
if (graph.terminalPoints.length > 0) {
|
|
449
|
+
for (const terminal of graph.terminalPoints.slice(0, 10)) {
|
|
450
|
+
const label = mermaidLabel(terminal);
|
|
451
|
+
if (!styledNodes.has(label)) {
|
|
452
|
+
lines.push(` style ${label} fill:#FFB6C1`);
|
|
453
|
+
styledNodes.add(label);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
return lines.join('\n');
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Generate markdown documentation for dependencies.
|
|
461
|
+
*/
|
|
462
|
+
export function generateDependencyMarkdown(graph, stats) {
|
|
463
|
+
const lines = [];
|
|
464
|
+
lines.push('## Tool Dependencies');
|
|
465
|
+
lines.push('');
|
|
466
|
+
if (graph.edges.length === 0) {
|
|
467
|
+
lines.push('No inter-tool dependencies detected.');
|
|
468
|
+
lines.push('');
|
|
469
|
+
return lines.join('\n');
|
|
470
|
+
}
|
|
471
|
+
lines.push(`Detected ${graph.edges.length} dependency relationship(s) between tools.`);
|
|
472
|
+
lines.push('');
|
|
473
|
+
// Mermaid diagram
|
|
474
|
+
if (graph.edges.length <= 50) {
|
|
475
|
+
lines.push('```mermaid');
|
|
476
|
+
lines.push(generateDependencyMermaid(graph));
|
|
477
|
+
lines.push('```');
|
|
478
|
+
lines.push('');
|
|
479
|
+
}
|
|
480
|
+
// Stats summary
|
|
481
|
+
lines.push('### Dependency Statistics');
|
|
482
|
+
lines.push('');
|
|
483
|
+
lines.push('| Metric | Value |');
|
|
484
|
+
lines.push('|--------|-------|');
|
|
485
|
+
lines.push(`| Total Dependencies | ${stats.totalEdges} |`);
|
|
486
|
+
lines.push(`| Avg. Dependencies/Tool | ${stats.avgDependencies.toFixed(1)} |`);
|
|
487
|
+
lines.push(`| Max Chain Length | ${stats.maxChainLength} |`);
|
|
488
|
+
lines.push(`| Entry Points | ${graph.entryPoints.length} |`);
|
|
489
|
+
lines.push(`| Terminal Points | ${graph.terminalPoints.length} |`);
|
|
490
|
+
lines.push('');
|
|
491
|
+
// Dependency types breakdown
|
|
492
|
+
const typeLabels = {
|
|
493
|
+
mention: 'Description Mentions',
|
|
494
|
+
output_input: 'Output → Input',
|
|
495
|
+
resource_ref: 'Resource References',
|
|
496
|
+
sequence: 'Sequence (implied)',
|
|
497
|
+
shared_resource: 'Shared Resource',
|
|
498
|
+
};
|
|
499
|
+
const typeCounts = Object.entries(stats.byType).filter(([_, count]) => count > 0);
|
|
500
|
+
if (typeCounts.length > 1) {
|
|
501
|
+
lines.push('#### By Relationship Type');
|
|
502
|
+
lines.push('');
|
|
503
|
+
lines.push('| Type | Count |');
|
|
504
|
+
lines.push('|------|-------|');
|
|
505
|
+
for (const [type, count] of typeCounts) {
|
|
506
|
+
lines.push(`| ${typeLabels[type]} | ${count} |`);
|
|
507
|
+
}
|
|
508
|
+
lines.push('');
|
|
509
|
+
}
|
|
510
|
+
// Most depended upon
|
|
511
|
+
if (stats.mostDependedUpon.length > 0) {
|
|
512
|
+
lines.push('#### Key Dependencies');
|
|
513
|
+
lines.push('');
|
|
514
|
+
lines.push('| Tool | Dependents |');
|
|
515
|
+
lines.push('|------|------------|');
|
|
516
|
+
for (const { tool, count } of stats.mostDependedUpon.slice(0, 5)) {
|
|
517
|
+
lines.push(`| \`${tool}\` | ${count} tools depend on it |`);
|
|
518
|
+
}
|
|
519
|
+
lines.push('');
|
|
520
|
+
}
|
|
521
|
+
// Dependency details table
|
|
522
|
+
if (graph.edges.length <= 30) {
|
|
523
|
+
lines.push('### Dependency Details');
|
|
524
|
+
lines.push('');
|
|
525
|
+
lines.push('| Tool | Depends On | Relationship | Confidence |');
|
|
526
|
+
lines.push('|------|-----------|--------------|------------|');
|
|
527
|
+
// Sort by target tool, then confidence
|
|
528
|
+
const sortedEdges = [...graph.edges].sort((a, b) => {
|
|
529
|
+
if (a.to !== b.to)
|
|
530
|
+
return a.to.localeCompare(b.to);
|
|
531
|
+
return b.confidence - a.confidence;
|
|
532
|
+
});
|
|
533
|
+
for (const edge of sortedEdges) {
|
|
534
|
+
const confidenceIcon = edge.confidence >= 0.7 ? '●' : edge.confidence >= 0.5 ? '◐' : '○';
|
|
535
|
+
lines.push(`| \`${edge.to}\` | \`${edge.from}\` | ${edge.description} | ${confidenceIcon} ${(edge.confidence * 100).toFixed(0)}% |`);
|
|
536
|
+
}
|
|
537
|
+
lines.push('');
|
|
538
|
+
}
|
|
539
|
+
// Cycles warning
|
|
540
|
+
if (graph.cycles.length > 0) {
|
|
541
|
+
lines.push('### ⚠️ Circular Dependencies');
|
|
542
|
+
lines.push('');
|
|
543
|
+
lines.push('The following circular dependencies were detected:');
|
|
544
|
+
lines.push('');
|
|
545
|
+
for (const cycle of graph.cycles.slice(0, 5)) {
|
|
546
|
+
lines.push(`- ${cycle.map(t => `\`${t}\``).join(' → ')}`);
|
|
547
|
+
}
|
|
548
|
+
lines.push('');
|
|
549
|
+
}
|
|
550
|
+
// Execution layers
|
|
551
|
+
if (graph.layers.length > 1) {
|
|
552
|
+
lines.push('### Suggested Execution Order');
|
|
553
|
+
lines.push('');
|
|
554
|
+
lines.push('Based on dependencies, tools can be organized into layers:');
|
|
555
|
+
lines.push('');
|
|
556
|
+
for (let i = 0; i < graph.layers.length && i < 5; i++) {
|
|
557
|
+
const layer = graph.layers[i];
|
|
558
|
+
lines.push(`${i + 1}. ${layer.map(t => `\`${t}\``).join(', ')}`);
|
|
559
|
+
}
|
|
560
|
+
if (graph.layers.length > 5) {
|
|
561
|
+
lines.push(`... and ${graph.layers.length - 5} more layers`);
|
|
562
|
+
}
|
|
563
|
+
lines.push('');
|
|
564
|
+
}
|
|
565
|
+
return lines.join('\n');
|
|
566
|
+
}
|
|
567
|
+
//# sourceMappingURL=dependency-analyzer.js.map
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deprecation Lifecycle Management
|
|
3
|
+
*
|
|
4
|
+
* Tracks tool deprecation status and warns consumers about deprecated tools.
|
|
5
|
+
* Supports grace periods, replacement suggestions, and removal date enforcement.
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolFingerprint, BehavioralBaseline, ChangeSeverity } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Deprecation status for a tool.
|
|
10
|
+
*/
|
|
11
|
+
export type DeprecationStatus = 'active' | 'deprecated' | 'sunset' | 'removed';
|
|
12
|
+
/**
|
|
13
|
+
* Deprecation warning for a single tool.
|
|
14
|
+
*/
|
|
15
|
+
export interface DeprecationWarning {
|
|
16
|
+
/** Tool name */
|
|
17
|
+
toolName: string;
|
|
18
|
+
/** Current deprecation status */
|
|
19
|
+
status: DeprecationStatus;
|
|
20
|
+
/** Severity of the warning */
|
|
21
|
+
severity: ChangeSeverity;
|
|
22
|
+
/** Warning message */
|
|
23
|
+
message: string;
|
|
24
|
+
/** When the tool was deprecated (if applicable) */
|
|
25
|
+
deprecatedAt?: Date;
|
|
26
|
+
/** Planned removal date (if applicable) */
|
|
27
|
+
removalDate?: Date;
|
|
28
|
+
/** Days until removal (negative if past) */
|
|
29
|
+
daysUntilRemoval?: number;
|
|
30
|
+
/** Suggested replacement tool */
|
|
31
|
+
replacementTool?: string;
|
|
32
|
+
/** Full deprecation notice from the tool */
|
|
33
|
+
deprecationNotice?: string;
|
|
34
|
+
/** Whether this tool is past its removal date */
|
|
35
|
+
isPastRemoval: boolean;
|
|
36
|
+
/** Whether this tool is within grace period */
|
|
37
|
+
isInGracePeriod: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Deprecation report for an entire baseline.
|
|
41
|
+
*/
|
|
42
|
+
export interface DeprecationReport {
|
|
43
|
+
/** All deprecation warnings */
|
|
44
|
+
warnings: DeprecationWarning[];
|
|
45
|
+
/** Number of deprecated tools */
|
|
46
|
+
deprecatedCount: number;
|
|
47
|
+
/** Number of tools past removal date */
|
|
48
|
+
expiredCount: number;
|
|
49
|
+
/** Number of tools within grace period */
|
|
50
|
+
gracePeriodCount: number;
|
|
51
|
+
/** Overall severity */
|
|
52
|
+
overallSeverity: ChangeSeverity;
|
|
53
|
+
/** Human-readable summary */
|
|
54
|
+
summary: string;
|
|
55
|
+
/** Whether there are any critical issues (past removal date) */
|
|
56
|
+
hasCriticalIssues: boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Deprecation configuration options.
|
|
60
|
+
*/
|
|
61
|
+
export interface DeprecationConfig {
|
|
62
|
+
/** Warn when using deprecated tools */
|
|
63
|
+
warnOnUsage: boolean;
|
|
64
|
+
/** Fail when using tools past their removal date */
|
|
65
|
+
failOnExpired: boolean;
|
|
66
|
+
/** Default grace period in days after removal date */
|
|
67
|
+
gracePeriodDays: number;
|
|
68
|
+
/** Severity for deprecated tools */
|
|
69
|
+
deprecatedSeverity: ChangeSeverity;
|
|
70
|
+
/** Severity for tools past removal date */
|
|
71
|
+
expiredSeverity: ChangeSeverity;
|
|
72
|
+
}
|
|
73
|
+
export { DEPRECATION } from '../constants.js';
|
|
74
|
+
/**
|
|
75
|
+
* Default deprecation configuration.
|
|
76
|
+
* Uses values from centralized constants.
|
|
77
|
+
*/
|
|
78
|
+
export declare const DEPRECATION_DEFAULTS: DeprecationConfig;
|
|
79
|
+
/**
|
|
80
|
+
* Days thresholds for warning levels.
|
|
81
|
+
* Uses values from centralized constants.
|
|
82
|
+
*/
|
|
83
|
+
export declare const DEPRECATION_THRESHOLDS: {
|
|
84
|
+
/** Warn about upcoming removal within this many days */
|
|
85
|
+
readonly UPCOMING_REMOVAL_DAYS: 30;
|
|
86
|
+
/** Critical warning within this many days */
|
|
87
|
+
readonly CRITICAL_REMOVAL_DAYS: 7;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Check all tools in a baseline for deprecation issues.
|
|
91
|
+
*/
|
|
92
|
+
export declare function checkDeprecations(baseline: BehavioralBaseline, config?: Partial<DeprecationConfig>): DeprecationReport;
|
|
93
|
+
/**
|
|
94
|
+
* Check a single tool for deprecation issues.
|
|
95
|
+
*/
|
|
96
|
+
export declare function checkToolDeprecation(tool: ToolFingerprint, now?: Date, config?: DeprecationConfig): DeprecationWarning | null;
|
|
97
|
+
/**
|
|
98
|
+
* Mark a tool as deprecated.
|
|
99
|
+
*/
|
|
100
|
+
export declare function markAsDeprecated(tool: ToolFingerprint, options?: {
|
|
101
|
+
notice?: string;
|
|
102
|
+
removalDate?: Date;
|
|
103
|
+
replacementTool?: string;
|
|
104
|
+
}): ToolFingerprint;
|
|
105
|
+
/**
|
|
106
|
+
* Clear deprecation status from a tool.
|
|
107
|
+
*/
|
|
108
|
+
export declare function clearDeprecation(tool: ToolFingerprint): ToolFingerprint;
|
|
109
|
+
/**
|
|
110
|
+
* Get all deprecated tools from a baseline.
|
|
111
|
+
*/
|
|
112
|
+
export declare function getDeprecatedTools(baseline: BehavioralBaseline): ToolFingerprint[];
|
|
113
|
+
/**
|
|
114
|
+
* Get tools that are past their removal date.
|
|
115
|
+
*/
|
|
116
|
+
export declare function getExpiredTools(baseline: BehavioralBaseline, now?: Date): ToolFingerprint[];
|
|
117
|
+
/**
|
|
118
|
+
* Get tools that will be removed within a specified number of days.
|
|
119
|
+
*/
|
|
120
|
+
export declare function getUpcomingRemovals(baseline: BehavioralBaseline, withinDays?: number, now?: Date): ToolFingerprint[];
|
|
121
|
+
/**
|
|
122
|
+
* Format deprecation warning for display.
|
|
123
|
+
*/
|
|
124
|
+
export declare function formatDeprecationWarning(warning: DeprecationWarning): string;
|
|
125
|
+
/**
|
|
126
|
+
* Format deprecation report for console output.
|
|
127
|
+
*/
|
|
128
|
+
export declare function formatDeprecationReport(report: DeprecationReport): string;
|
|
129
|
+
/**
|
|
130
|
+
* Check if deprecation report should cause failure.
|
|
131
|
+
*/
|
|
132
|
+
export declare function shouldFailOnDeprecation(report: DeprecationReport, config?: Partial<DeprecationConfig>): boolean;
|
|
133
|
+
//# sourceMappingURL=deprecation-tracker.d.ts.map
|