@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,513 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow auto-generator - generates workflow YAML from discovered tools.
|
|
3
|
+
*
|
|
4
|
+
* This module analyzes tool descriptions and schemas to automatically
|
|
5
|
+
* generate test workflows that represent common usage patterns.
|
|
6
|
+
* Unlike the LLM-powered WorkflowDiscoverer, this uses heuristics
|
|
7
|
+
* for deterministic workflow generation in check mode.
|
|
8
|
+
*/
|
|
9
|
+
import { WORKFLOW } from '../constants.js';
|
|
10
|
+
/**
|
|
11
|
+
* Default options for workflow generation.
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_OPTIONS = {
|
|
14
|
+
maxWorkflows: WORKFLOW.MAX_DISCOVERED_WORKFLOWS,
|
|
15
|
+
minSteps: WORKFLOW.MIN_WORKFLOW_STEPS,
|
|
16
|
+
maxSteps: WORKFLOW.MAX_WORKFLOW_STEPS,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Common CRUD operation prefixes for pattern matching.
|
|
20
|
+
*/
|
|
21
|
+
const CRUD_PREFIXES = {
|
|
22
|
+
create: ['create', 'add', 'new', 'insert', 'post', 'make'],
|
|
23
|
+
read: ['get', 'read', 'fetch', 'retrieve', 'find', 'list', 'search', 'query'],
|
|
24
|
+
update: ['update', 'edit', 'modify', 'patch', 'set', 'change'],
|
|
25
|
+
delete: ['delete', 'remove', 'destroy', 'clear', 'reset'],
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Workflow relationship patterns found in tool descriptions.
|
|
29
|
+
*/
|
|
30
|
+
const RELATIONSHIP_PATTERNS = [
|
|
31
|
+
{ pattern: /after\s+(?:calling\s+)?['"`]?(\w+)['"`]?/i, type: 'after' },
|
|
32
|
+
{ pattern: /requires?\s+(?:output\s+from\s+)?['"`]?(\w+)['"`]?/i, type: 'requires' },
|
|
33
|
+
{ pattern: /use\s+(?:the\s+)?(?:result|output)\s+(?:of|from)\s+['"`]?(\w+)['"`]?/i, type: 'uses' },
|
|
34
|
+
{ pattern: /(?:first|before)\s+(?:call\s+)?['"`]?(\w+)['"`]?/i, type: 'after' },
|
|
35
|
+
{ pattern: /chain\s+(?:with\s+)?['"`]?(\w+)['"`]?/i, type: 'chains' },
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Common parameter patterns that suggest data flow.
|
|
39
|
+
*/
|
|
40
|
+
const PARAMETER_FLOW_PATTERNS = [
|
|
41
|
+
{ paramPattern: /^(item|access|session|auth)_?token$/i, sourceField: 'token' },
|
|
42
|
+
{ paramPattern: /^(item|access|session)_?id$/i, sourceField: 'id' },
|
|
43
|
+
{ paramPattern: /^(public|link)_?token$/i, sourceField: 'link_token' },
|
|
44
|
+
{ paramPattern: /^(cursor|next_?cursor|page_?token)$/i, sourceField: 'next_cursor' },
|
|
45
|
+
{ paramPattern: /^(file|resource|entity)_?path$/i, sourceField: 'path' },
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Generate workflows from available tools using pattern matching.
|
|
49
|
+
*
|
|
50
|
+
* This function analyzes tool names, descriptions, and schemas to
|
|
51
|
+
* identify common workflow patterns like CRUD operations, auth flows,
|
|
52
|
+
* and chained data processing.
|
|
53
|
+
*
|
|
54
|
+
* @param tools - Available MCP tools
|
|
55
|
+
* @param options - Generation options
|
|
56
|
+
* @returns Array of generated workflows
|
|
57
|
+
*/
|
|
58
|
+
export function generateWorkflowsFromTools(tools, options = {}) {
|
|
59
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
60
|
+
if (tools.length < 2) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const workflows = [];
|
|
64
|
+
// Strategy 1: Find CRUD patterns
|
|
65
|
+
const crudWorkflows = findCrudWorkflows(tools, opts);
|
|
66
|
+
workflows.push(...crudWorkflows);
|
|
67
|
+
// Strategy 2: Find relationship-based workflows from descriptions
|
|
68
|
+
const relationshipWorkflows = findRelationshipWorkflows(tools, opts);
|
|
69
|
+
workflows.push(...relationshipWorkflows);
|
|
70
|
+
// Strategy 3: Find parameter-based workflows (data flow patterns)
|
|
71
|
+
const parameterWorkflows = findParameterFlowWorkflows(tools, opts);
|
|
72
|
+
workflows.push(...parameterWorkflows);
|
|
73
|
+
// Deduplicate workflows by ID
|
|
74
|
+
const seen = new Set();
|
|
75
|
+
const uniqueWorkflows = workflows.filter(w => {
|
|
76
|
+
if (seen.has(w.id))
|
|
77
|
+
return false;
|
|
78
|
+
seen.add(w.id);
|
|
79
|
+
return true;
|
|
80
|
+
});
|
|
81
|
+
// Limit to max workflows
|
|
82
|
+
return uniqueWorkflows.slice(0, opts.maxWorkflows);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Find CRUD-based workflows by grouping tools by resource type.
|
|
86
|
+
*/
|
|
87
|
+
function findCrudWorkflows(tools, opts) {
|
|
88
|
+
const workflows = [];
|
|
89
|
+
const toolsByResource = groupToolsByResource(tools);
|
|
90
|
+
for (const [resource, resourceTools] of toolsByResource.entries()) {
|
|
91
|
+
// Need at least 2 tools for a workflow
|
|
92
|
+
if (resourceTools.length < opts.minSteps)
|
|
93
|
+
continue;
|
|
94
|
+
// Try to build create-read workflow
|
|
95
|
+
const createTool = resourceTools.find(t => matchesCrudOperation(t.name, 'create'));
|
|
96
|
+
const readTool = resourceTools.find(t => matchesCrudOperation(t.name, 'read'));
|
|
97
|
+
if (createTool && readTool) {
|
|
98
|
+
workflows.push({
|
|
99
|
+
id: `crud_create_read_${resource}`,
|
|
100
|
+
name: `Create and Read ${capitalize(resource)}`,
|
|
101
|
+
description: `Create a new ${resource} and verify it can be retrieved`,
|
|
102
|
+
expectedOutcome: `Successfully create and read ${resource}`,
|
|
103
|
+
steps: [
|
|
104
|
+
{
|
|
105
|
+
tool: createTool.name,
|
|
106
|
+
description: `Create a new ${resource}`,
|
|
107
|
+
args: generateMinimalArgs(createTool),
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
tool: readTool.name,
|
|
111
|
+
description: `Retrieve the created ${resource}`,
|
|
112
|
+
argMapping: inferArgMapping(createTool, readTool, 0),
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
discovered: true,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// Try to build list workflow
|
|
119
|
+
const listTool = resourceTools.find(t => /^(list|get_all|search)_/i.test(t.name));
|
|
120
|
+
if (listTool && readTool && listTool !== readTool) {
|
|
121
|
+
workflows.push({
|
|
122
|
+
id: `crud_list_read_${resource}`,
|
|
123
|
+
name: `List and Read ${capitalize(resource)}`,
|
|
124
|
+
description: `List ${resource}s and get details of the first one`,
|
|
125
|
+
expectedOutcome: `Successfully list and retrieve ${resource} details`,
|
|
126
|
+
steps: [
|
|
127
|
+
{
|
|
128
|
+
tool: listTool.name,
|
|
129
|
+
description: `List available ${resource}s`,
|
|
130
|
+
args: generateMinimalArgs(listTool),
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
tool: readTool.name,
|
|
134
|
+
description: `Get details of first ${resource}`,
|
|
135
|
+
argMapping: inferListToDetailMapping(listTool, readTool),
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
discovered: true,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return workflows;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Find workflows based on relationship patterns in descriptions.
|
|
146
|
+
*/
|
|
147
|
+
function findRelationshipWorkflows(tools, opts) {
|
|
148
|
+
const workflows = [];
|
|
149
|
+
const toolsByName = new Map(tools.map(t => [t.name.toLowerCase(), t]));
|
|
150
|
+
for (const tool of tools) {
|
|
151
|
+
const description = tool.description || '';
|
|
152
|
+
for (const { pattern, type } of RELATIONSHIP_PATTERNS) {
|
|
153
|
+
const match = description.match(pattern);
|
|
154
|
+
if (!match)
|
|
155
|
+
continue;
|
|
156
|
+
const referencedToolName = match[1].toLowerCase();
|
|
157
|
+
const referencedTool = toolsByName.get(referencedToolName);
|
|
158
|
+
if (!referencedTool || referencedTool.name === tool.name)
|
|
159
|
+
continue;
|
|
160
|
+
// Build workflow based on relationship type
|
|
161
|
+
const steps = [];
|
|
162
|
+
if (type === 'after' || type === 'requires' || type === 'uses') {
|
|
163
|
+
// Referenced tool comes first
|
|
164
|
+
steps.push({
|
|
165
|
+
tool: referencedTool.name,
|
|
166
|
+
description: referencedTool.description || `Call ${referencedTool.name}`,
|
|
167
|
+
args: generateMinimalArgs(referencedTool),
|
|
168
|
+
});
|
|
169
|
+
steps.push({
|
|
170
|
+
tool: tool.name,
|
|
171
|
+
description: tool.description || `Call ${tool.name}`,
|
|
172
|
+
argMapping: inferArgMapping(referencedTool, tool, 0),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Current tool comes first (chains pattern)
|
|
177
|
+
steps.push({
|
|
178
|
+
tool: tool.name,
|
|
179
|
+
description: tool.description || `Call ${tool.name}`,
|
|
180
|
+
args: generateMinimalArgs(tool),
|
|
181
|
+
});
|
|
182
|
+
steps.push({
|
|
183
|
+
tool: referencedTool.name,
|
|
184
|
+
description: referencedTool.description || `Call ${referencedTool.name}`,
|
|
185
|
+
argMapping: inferArgMapping(tool, referencedTool, 0),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
if (steps.length >= opts.minSteps) {
|
|
189
|
+
const workflowId = `rel_${tool.name}_${referencedTool.name}`.toLowerCase().replace(/[^a-z0-9]+/g, '_');
|
|
190
|
+
workflows.push({
|
|
191
|
+
id: workflowId,
|
|
192
|
+
name: `${capitalize(steps[0].tool)} to ${capitalize(steps[1].tool)}`,
|
|
193
|
+
description: `Workflow discovered from tool description relationship`,
|
|
194
|
+
expectedOutcome: `Successfully chain ${steps[0].tool} and ${steps[1].tool}`,
|
|
195
|
+
steps,
|
|
196
|
+
discovered: true,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return workflows;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Find workflows based on parameter name patterns that suggest data flow.
|
|
205
|
+
*/
|
|
206
|
+
function findParameterFlowWorkflows(tools, _opts) {
|
|
207
|
+
const workflows = [];
|
|
208
|
+
// Map tools by what they might produce based on description/name
|
|
209
|
+
const producerTools = new Map();
|
|
210
|
+
for (const tool of tools) {
|
|
211
|
+
const description = (tool.description || '').toLowerCase();
|
|
212
|
+
const name = tool.name.toLowerCase();
|
|
213
|
+
// Tools that create/generate tokens
|
|
214
|
+
if (/(?:create|generate|get).*(?:token|link)/i.test(name) ||
|
|
215
|
+
/returns?\s+(?:a\s+)?(?:link_?)?token/i.test(description)) {
|
|
216
|
+
producerTools.set('token', tool);
|
|
217
|
+
}
|
|
218
|
+
// Tools that list/return items with IDs
|
|
219
|
+
if (/^list_|^get_all_|^search_/i.test(name)) {
|
|
220
|
+
const resource = extractResourceName(name);
|
|
221
|
+
if (resource) {
|
|
222
|
+
producerTools.set(`${resource}_list`, tool);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Find consumer tools and create workflows
|
|
227
|
+
for (const tool of tools) {
|
|
228
|
+
const schema = tool.inputSchema;
|
|
229
|
+
if (!schema?.properties)
|
|
230
|
+
continue;
|
|
231
|
+
for (const paramName of Object.keys(schema.properties)) {
|
|
232
|
+
for (const { paramPattern, sourceField } of PARAMETER_FLOW_PATTERNS) {
|
|
233
|
+
if (!paramPattern.test(paramName))
|
|
234
|
+
continue;
|
|
235
|
+
// Find a producer for this parameter
|
|
236
|
+
const producerKey = sourceField === 'token' ? 'token' : extractResourceName(paramName) + '_list';
|
|
237
|
+
const producer = producerTools.get(producerKey) || producerTools.get('token');
|
|
238
|
+
if (!producer || producer.name === tool.name)
|
|
239
|
+
continue;
|
|
240
|
+
const workflowId = `flow_${producer.name}_${tool.name}`.toLowerCase().replace(/[^a-z0-9]+/g, '_');
|
|
241
|
+
// Check if we already have this workflow
|
|
242
|
+
if (workflows.some(w => w.id === workflowId))
|
|
243
|
+
continue;
|
|
244
|
+
workflows.push({
|
|
245
|
+
id: workflowId,
|
|
246
|
+
name: `${capitalize(producer.name)} to ${capitalize(tool.name)}`,
|
|
247
|
+
description: `Data flow workflow: ${producer.name} produces input for ${tool.name}`,
|
|
248
|
+
expectedOutcome: `Successfully pass ${sourceField} from ${producer.name} to ${tool.name}`,
|
|
249
|
+
steps: [
|
|
250
|
+
{
|
|
251
|
+
tool: producer.name,
|
|
252
|
+
description: producer.description || `Call ${producer.name}`,
|
|
253
|
+
args: generateMinimalArgs(producer),
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
tool: tool.name,
|
|
257
|
+
description: tool.description || `Call ${tool.name}`,
|
|
258
|
+
argMapping: {
|
|
259
|
+
[paramName]: `$steps[0].result.${sourceField}`,
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
discovered: true,
|
|
264
|
+
});
|
|
265
|
+
// Only one workflow per tool pair
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return workflows;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Group tools by their inferred resource type.
|
|
274
|
+
*/
|
|
275
|
+
function groupToolsByResource(tools) {
|
|
276
|
+
const groups = new Map();
|
|
277
|
+
for (const tool of tools) {
|
|
278
|
+
const resource = extractResourceName(tool.name);
|
|
279
|
+
if (!resource)
|
|
280
|
+
continue;
|
|
281
|
+
if (!groups.has(resource)) {
|
|
282
|
+
groups.set(resource, []);
|
|
283
|
+
}
|
|
284
|
+
groups.get(resource).push(tool);
|
|
285
|
+
}
|
|
286
|
+
return groups;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Extract resource name from a tool name (e.g., "get_user" -> "user").
|
|
290
|
+
*/
|
|
291
|
+
function extractResourceName(toolName) {
|
|
292
|
+
// Remove common prefixes
|
|
293
|
+
let name = toolName.toLowerCase();
|
|
294
|
+
for (const prefixes of Object.values(CRUD_PREFIXES)) {
|
|
295
|
+
for (const prefix of prefixes) {
|
|
296
|
+
if (name.startsWith(prefix + '_')) {
|
|
297
|
+
name = name.slice(prefix.length + 1);
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
if (name.startsWith(prefix)) {
|
|
301
|
+
name = name.slice(prefix.length);
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// Clean up remaining underscores and pluralization
|
|
307
|
+
name = name.replace(/^_+|_+$/g, '');
|
|
308
|
+
name = name.replace(/s$/, ''); // Simple depluralization
|
|
309
|
+
return name || null;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Check if a tool name matches a CRUD operation type.
|
|
313
|
+
*/
|
|
314
|
+
function matchesCrudOperation(toolName, operation) {
|
|
315
|
+
const name = toolName.toLowerCase();
|
|
316
|
+
return CRUD_PREFIXES[operation].some(prefix => name.startsWith(prefix + '_') || name.startsWith(prefix));
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Generate minimal arguments for a tool based on its schema.
|
|
320
|
+
* Only includes required parameters with placeholder values.
|
|
321
|
+
*/
|
|
322
|
+
function generateMinimalArgs(tool) {
|
|
323
|
+
const schema = tool.inputSchema;
|
|
324
|
+
if (!schema?.properties || !schema.required) {
|
|
325
|
+
return {};
|
|
326
|
+
}
|
|
327
|
+
const args = {};
|
|
328
|
+
for (const reqParam of schema.required) {
|
|
329
|
+
const propSchema = schema.properties[reqParam];
|
|
330
|
+
if (!propSchema)
|
|
331
|
+
continue;
|
|
332
|
+
// Use default if available
|
|
333
|
+
if (propSchema.default !== undefined) {
|
|
334
|
+
args[reqParam] = propSchema.default;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
// Use first enum value if available
|
|
338
|
+
if (propSchema.enum && propSchema.enum.length > 0) {
|
|
339
|
+
args[reqParam] = propSchema.enum[0];
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
// Generate placeholder based on type
|
|
343
|
+
switch (propSchema.type) {
|
|
344
|
+
case 'string':
|
|
345
|
+
args[reqParam] = `test_${reqParam}`;
|
|
346
|
+
break;
|
|
347
|
+
case 'number':
|
|
348
|
+
case 'integer':
|
|
349
|
+
args[reqParam] = 1;
|
|
350
|
+
break;
|
|
351
|
+
case 'boolean':
|
|
352
|
+
args[reqParam] = true;
|
|
353
|
+
break;
|
|
354
|
+
case 'array':
|
|
355
|
+
args[reqParam] = [];
|
|
356
|
+
break;
|
|
357
|
+
case 'object':
|
|
358
|
+
args[reqParam] = {};
|
|
359
|
+
break;
|
|
360
|
+
default:
|
|
361
|
+
args[reqParam] = `test_${reqParam}`;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return args;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Infer argument mapping from a source tool to a target tool.
|
|
368
|
+
*/
|
|
369
|
+
function inferArgMapping(_sourceTool, targetTool, sourceStepIndex) {
|
|
370
|
+
const targetSchema = targetTool.inputSchema;
|
|
371
|
+
if (!targetSchema?.properties)
|
|
372
|
+
return undefined;
|
|
373
|
+
const mapping = {};
|
|
374
|
+
const targetParams = Object.keys(targetSchema.properties);
|
|
375
|
+
// Common result field names to try
|
|
376
|
+
const commonResultFields = ['id', 'result', 'data', 'token', 'value', 'output'];
|
|
377
|
+
for (const param of targetParams) {
|
|
378
|
+
const paramLower = param.toLowerCase();
|
|
379
|
+
// Look for ID fields
|
|
380
|
+
if (paramLower.includes('id')) {
|
|
381
|
+
mapping[param] = `$steps[${sourceStepIndex}].result.id`;
|
|
382
|
+
}
|
|
383
|
+
// Look for token fields
|
|
384
|
+
else if (paramLower.includes('token')) {
|
|
385
|
+
const tokenType = paramLower.replace('_token', '').replace('token', '');
|
|
386
|
+
if (tokenType) {
|
|
387
|
+
mapping[param] = `$steps[${sourceStepIndex}].result.${tokenType}_token`;
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
mapping[param] = `$steps[${sourceStepIndex}].result.token`;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// Look for matching field names
|
|
394
|
+
else if (commonResultFields.includes(paramLower)) {
|
|
395
|
+
mapping[param] = `$steps[${sourceStepIndex}].result.${paramLower}`;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return Object.keys(mapping).length > 0 ? mapping : undefined;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Infer mapping from a list operation to a detail operation.
|
|
402
|
+
*/
|
|
403
|
+
function inferListToDetailMapping(listTool, detailTool) {
|
|
404
|
+
const detailSchema = detailTool.inputSchema;
|
|
405
|
+
if (!detailSchema?.properties)
|
|
406
|
+
return undefined;
|
|
407
|
+
const mapping = {};
|
|
408
|
+
const detailParams = Object.keys(detailSchema.properties);
|
|
409
|
+
for (const param of detailParams) {
|
|
410
|
+
const paramLower = param.toLowerCase();
|
|
411
|
+
// Map ID parameters to first item in list
|
|
412
|
+
if (paramLower.includes('id')) {
|
|
413
|
+
// Infer the array name from the list tool name
|
|
414
|
+
const resource = extractResourceName(listTool.name);
|
|
415
|
+
const arrayName = resource ? `${resource}s` : 'items';
|
|
416
|
+
mapping[param] = `$steps[0].result.${arrayName}[0].id`;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return Object.keys(mapping).length > 0 ? mapping : undefined;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Capitalize the first letter of a string.
|
|
423
|
+
*/
|
|
424
|
+
function capitalize(str) {
|
|
425
|
+
return str.charAt(0).toUpperCase() + str.slice(1).replace(/_/g, ' ');
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Generate YAML content for workflows.
|
|
429
|
+
*/
|
|
430
|
+
export function generateWorkflowYamlContent(workflows) {
|
|
431
|
+
const lines = [
|
|
432
|
+
'# Auto-generated workflow definitions',
|
|
433
|
+
'# Generated by: bellwether check --generate-workflows',
|
|
434
|
+
'# ',
|
|
435
|
+
'# Usage: bellwether check --workflows ./bellwether-workflows.yaml',
|
|
436
|
+
'# ',
|
|
437
|
+
'# You can modify these workflows to add assertions, customize arguments,',
|
|
438
|
+
'# or add additional steps. See the Bellwether documentation for more details.',
|
|
439
|
+
'',
|
|
440
|
+
];
|
|
441
|
+
for (let i = 0; i < workflows.length; i++) {
|
|
442
|
+
const workflow = workflows[i];
|
|
443
|
+
if (i > 0) {
|
|
444
|
+
lines.push('---');
|
|
445
|
+
}
|
|
446
|
+
lines.push(`id: ${workflow.id}`);
|
|
447
|
+
lines.push(`name: "${escapeYamlString(workflow.name)}"`);
|
|
448
|
+
lines.push(`description: "${escapeYamlString(workflow.description)}"`);
|
|
449
|
+
lines.push(`expectedOutcome: "${escapeYamlString(workflow.expectedOutcome)}"`);
|
|
450
|
+
lines.push('');
|
|
451
|
+
lines.push('steps:');
|
|
452
|
+
for (const step of workflow.steps) {
|
|
453
|
+
lines.push(` - tool: ${step.tool}`);
|
|
454
|
+
lines.push(` description: "${escapeYamlString(step.description)}"`);
|
|
455
|
+
if (step.args && Object.keys(step.args).length > 0) {
|
|
456
|
+
lines.push(' args:');
|
|
457
|
+
for (const [key, value] of Object.entries(step.args)) {
|
|
458
|
+
const formattedValue = formatYamlValue(value);
|
|
459
|
+
lines.push(` ${key}: ${formattedValue}`);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (step.argMapping && Object.keys(step.argMapping).length > 0) {
|
|
463
|
+
lines.push(' argMapping:');
|
|
464
|
+
for (const [key, value] of Object.entries(step.argMapping)) {
|
|
465
|
+
lines.push(` ${key}: "${value}"`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (step.optional) {
|
|
469
|
+
lines.push(' optional: true');
|
|
470
|
+
}
|
|
471
|
+
// Add empty assertions section as a template
|
|
472
|
+
lines.push(' # assertions:');
|
|
473
|
+
lines.push(' # - path: "$.result"');
|
|
474
|
+
lines.push(' # condition: exists');
|
|
475
|
+
}
|
|
476
|
+
lines.push('');
|
|
477
|
+
}
|
|
478
|
+
return lines.join('\n');
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Escape a string for YAML double-quoted strings.
|
|
482
|
+
*/
|
|
483
|
+
function escapeYamlString(str) {
|
|
484
|
+
return str
|
|
485
|
+
.replace(/\\/g, '\\\\')
|
|
486
|
+
.replace(/"/g, '\\"')
|
|
487
|
+
.replace(/\n/g, '\\n');
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Format a value for YAML output.
|
|
491
|
+
*/
|
|
492
|
+
function formatYamlValue(value) {
|
|
493
|
+
if (value === null)
|
|
494
|
+
return 'null';
|
|
495
|
+
if (value === undefined)
|
|
496
|
+
return '~';
|
|
497
|
+
if (typeof value === 'string')
|
|
498
|
+
return `"${escapeYamlString(value)}"`;
|
|
499
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
500
|
+
return String(value);
|
|
501
|
+
if (Array.isArray(value)) {
|
|
502
|
+
if (value.length === 0)
|
|
503
|
+
return '[]';
|
|
504
|
+
return JSON.stringify(value);
|
|
505
|
+
}
|
|
506
|
+
if (typeof value === 'object') {
|
|
507
|
+
if (Object.keys(value).length === 0)
|
|
508
|
+
return '{}';
|
|
509
|
+
return JSON.stringify(value);
|
|
510
|
+
}
|
|
511
|
+
return String(value);
|
|
512
|
+
}
|
|
513
|
+
//# sourceMappingURL=auto-generator.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow discovery - uses LLM to identify likely tool workflows.
|
|
3
|
+
*/
|
|
4
|
+
import type { MCPTool } from '../transport/types.js';
|
|
5
|
+
import type { LLMClient } from '../llm/client.js';
|
|
6
|
+
import type { Workflow, WorkflowDiscoveryOptions } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Discovers likely workflows from a set of tools.
|
|
9
|
+
*/
|
|
10
|
+
export declare class WorkflowDiscoverer {
|
|
11
|
+
private llm;
|
|
12
|
+
private options;
|
|
13
|
+
constructor(llm: LLMClient, options?: WorkflowDiscoveryOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Discover workflows from available tools.
|
|
16
|
+
*/
|
|
17
|
+
discover(tools: MCPTool[]): Promise<Workflow[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Extract parameter information from a tool schema.
|
|
20
|
+
*/
|
|
21
|
+
private extractParams;
|
|
22
|
+
/**
|
|
23
|
+
* Normalize and validate discovered workflows.
|
|
24
|
+
*/
|
|
25
|
+
private normalizeWorkflows;
|
|
26
|
+
/**
|
|
27
|
+
* Normalize a workflow step.
|
|
28
|
+
*/
|
|
29
|
+
private normalizeStep;
|
|
30
|
+
/**
|
|
31
|
+
* Generate a URL-safe ID from a name.
|
|
32
|
+
*/
|
|
33
|
+
private generateId;
|
|
34
|
+
/**
|
|
35
|
+
* Fallback discovery when LLM fails.
|
|
36
|
+
* Tries to identify tools that might work together based on naming patterns.
|
|
37
|
+
*/
|
|
38
|
+
private fallbackDiscovery;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=discovery.d.ts.map
|