@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,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Baseline versioning using CLI package version.
|
|
3
|
+
*
|
|
4
|
+
* Compatibility Rules:
|
|
5
|
+
* - Same CLI major version = COMPATIBLE (can compare baselines)
|
|
6
|
+
* - Different CLI major version = INCOMPATIBLE (requires migration)
|
|
7
|
+
*
|
|
8
|
+
* This aligns with semantic versioning: major version changes signal
|
|
9
|
+
* breaking changes, including baseline format changes.
|
|
10
|
+
*/
|
|
11
|
+
import { VERSION } from '../version.js';
|
|
12
|
+
/**
|
|
13
|
+
* Get the current CLI version for baseline creation.
|
|
14
|
+
*/
|
|
15
|
+
export function getBaselineVersion() {
|
|
16
|
+
return VERSION;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Error thrown when baseline versions are incompatible.
|
|
20
|
+
*/
|
|
21
|
+
export class BaselineVersionError extends Error {
|
|
22
|
+
sourceVersion;
|
|
23
|
+
targetVersion;
|
|
24
|
+
constructor(message, sourceVersion, targetVersion) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.sourceVersion = sourceVersion;
|
|
27
|
+
this.targetVersion = targetVersion;
|
|
28
|
+
this.name = 'BaselineVersionError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse a version string into its semantic components.
|
|
33
|
+
*
|
|
34
|
+
* Handles:
|
|
35
|
+
* - Full semver: "1.0.0" -> { major: 1, minor: 0, patch: 0 }
|
|
36
|
+
* - Partial semver: "1.0" -> { major: 1, minor: 0, patch: 0 }
|
|
37
|
+
* - Legacy numeric: 1 -> { major: 1, minor: 0, patch: 0 }
|
|
38
|
+
*
|
|
39
|
+
* @param version - Version string or number to parse
|
|
40
|
+
* @returns Parsed version components
|
|
41
|
+
*/
|
|
42
|
+
export function parseVersion(version) {
|
|
43
|
+
// Handle undefined/null - treat as current version
|
|
44
|
+
if (version === undefined || version === null) {
|
|
45
|
+
return parseVersion(VERSION);
|
|
46
|
+
}
|
|
47
|
+
// Handle legacy numeric version (e.g., version: 1)
|
|
48
|
+
if (typeof version === 'number') {
|
|
49
|
+
return {
|
|
50
|
+
major: version,
|
|
51
|
+
minor: 0,
|
|
52
|
+
patch: 0,
|
|
53
|
+
raw: `${version}.0.0`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Parse semver string
|
|
57
|
+
const parts = version.split('.').map(Number);
|
|
58
|
+
// Validate parsed numbers
|
|
59
|
+
const major = Number.isNaN(parts[0]) ? 0 : parts[0];
|
|
60
|
+
const minor = Number.isNaN(parts[1]) ? 0 : (parts[1] ?? 0);
|
|
61
|
+
const patch = Number.isNaN(parts[2]) ? 0 : (parts[2] ?? 0);
|
|
62
|
+
return {
|
|
63
|
+
major,
|
|
64
|
+
minor,
|
|
65
|
+
patch,
|
|
66
|
+
raw: `${major}.${minor}.${patch}`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check if two versions are compatible for baseline comparison.
|
|
71
|
+
*
|
|
72
|
+
* Versions are compatible if they share the same major version.
|
|
73
|
+
*
|
|
74
|
+
* @param v1 - First version
|
|
75
|
+
* @param v2 - Second version
|
|
76
|
+
* @returns true if compatible, false otherwise
|
|
77
|
+
*/
|
|
78
|
+
export function areVersionsCompatible(v1, v2) {
|
|
79
|
+
return v1.major === v2.major;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Compare two versions and return -1, 0, or 1.
|
|
83
|
+
*
|
|
84
|
+
* @param v1 - First version
|
|
85
|
+
* @param v2 - Second version
|
|
86
|
+
* @returns -1 if v1 < v2, 0 if equal, 1 if v1 > v2
|
|
87
|
+
*/
|
|
88
|
+
export function compareVersions(v1, v2) {
|
|
89
|
+
if (v1.major !== v2.major) {
|
|
90
|
+
return v1.major < v2.major ? -1 : 1;
|
|
91
|
+
}
|
|
92
|
+
if (v1.minor !== v2.minor) {
|
|
93
|
+
return v1.minor < v2.minor ? -1 : 1;
|
|
94
|
+
}
|
|
95
|
+
if (v1.patch !== v2.patch) {
|
|
96
|
+
return v1.patch < v2.patch ? -1 : 1;
|
|
97
|
+
}
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get a warning message for version differences, or null if versions are identical.
|
|
102
|
+
*
|
|
103
|
+
* @param v1 - First version (source/baseline)
|
|
104
|
+
* @param v2 - Second version (target/current)
|
|
105
|
+
* @returns Warning message or null
|
|
106
|
+
*/
|
|
107
|
+
export function getCompatibilityWarning(v1, v2) {
|
|
108
|
+
if (v1.major !== v2.major) {
|
|
109
|
+
return (`Baseline CLI versions are incompatible: v${v1.raw} vs v${v2.raw}. ` +
|
|
110
|
+
`Major version mismatch may cause incorrect comparison results. ` +
|
|
111
|
+
`Use \`bellwether baseline migrate\` to upgrade baselines to the current format.`);
|
|
112
|
+
}
|
|
113
|
+
if (v1.minor !== v2.minor || v1.patch !== v2.patch) {
|
|
114
|
+
return (`Baseline CLI versions differ: v${v1.raw} vs v${v2.raw}. ` +
|
|
115
|
+
`Comparison should work correctly, but some newer fields may not be present in the older baseline.`);
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Check version compatibility and return detailed result.
|
|
121
|
+
*
|
|
122
|
+
* @param sourceVersion - Version of the source/baseline
|
|
123
|
+
* @param targetVersion - Version of the target/current
|
|
124
|
+
* @returns Compatibility result with details
|
|
125
|
+
*/
|
|
126
|
+
export function checkVersionCompatibility(sourceVersion, targetVersion) {
|
|
127
|
+
const v1 = parseVersion(sourceVersion);
|
|
128
|
+
const v2 = parseVersion(targetVersion);
|
|
129
|
+
return {
|
|
130
|
+
compatible: areVersionsCompatible(v1, v2),
|
|
131
|
+
warning: getCompatibilityWarning(v1, v2),
|
|
132
|
+
sourceVersion: v1.raw,
|
|
133
|
+
targetVersion: v2.raw,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Assert that two versions are compatible, throwing an error if not.
|
|
138
|
+
*
|
|
139
|
+
* @param sourceVersion - Version of the source/baseline
|
|
140
|
+
* @param targetVersion - Version of the target/current
|
|
141
|
+
* @throws BaselineVersionError if versions are incompatible
|
|
142
|
+
*/
|
|
143
|
+
export function assertVersionCompatibility(sourceVersion, targetVersion) {
|
|
144
|
+
const v1 = parseVersion(sourceVersion);
|
|
145
|
+
const v2 = parseVersion(targetVersion);
|
|
146
|
+
if (!areVersionsCompatible(v1, v2)) {
|
|
147
|
+
throw new BaselineVersionError(`Cannot compare baselines with incompatible CLI versions: v${v1.raw} vs v${v2.raw}. ` +
|
|
148
|
+
`Use \`bellwether baseline migrate\` to upgrade the older baseline, ` +
|
|
149
|
+
`or use --ignore-version-mismatch to force comparison (results may be incorrect).`, v1.raw, v2.raw);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Format a version for display.
|
|
154
|
+
*
|
|
155
|
+
* @param version - Version to format
|
|
156
|
+
* @returns Formatted version string like "v1.0.0"
|
|
157
|
+
*/
|
|
158
|
+
export function formatVersion(version) {
|
|
159
|
+
const parsed = parseVersion(version);
|
|
160
|
+
return `v${parsed.raw}`;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Check if a version is the current CLI version.
|
|
164
|
+
*
|
|
165
|
+
* @param version - Version to check
|
|
166
|
+
* @returns true if version matches current CLI version
|
|
167
|
+
*/
|
|
168
|
+
export function isCurrentVersion(version) {
|
|
169
|
+
const parsed = parseVersion(version);
|
|
170
|
+
const current = parseVersion(VERSION);
|
|
171
|
+
return compareVersions(parsed, current) === 0;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check if a version is older than the current CLI version.
|
|
175
|
+
*
|
|
176
|
+
* @param version - Version to check
|
|
177
|
+
* @returns true if version is older than current
|
|
178
|
+
*/
|
|
179
|
+
export function isOlderVersion(version) {
|
|
180
|
+
const parsed = parseVersion(version);
|
|
181
|
+
const current = parseVersion(VERSION);
|
|
182
|
+
return compareVersions(parsed, current) < 0;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Check if a version is newer than the current CLI version.
|
|
186
|
+
*
|
|
187
|
+
* @param version - Version to check
|
|
188
|
+
* @returns true if version is newer than current
|
|
189
|
+
*/
|
|
190
|
+
export function isNewerVersion(version) {
|
|
191
|
+
const parsed = parseVersion(version);
|
|
192
|
+
const current = parseVersion(VERSION);
|
|
193
|
+
return compareVersions(parsed, current) > 0;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Check if a baseline version requires migration (different major version).
|
|
197
|
+
*
|
|
198
|
+
* @param version - Version to check
|
|
199
|
+
* @returns true if baseline needs migration to be compatible
|
|
200
|
+
*/
|
|
201
|
+
export function requiresMigration(version) {
|
|
202
|
+
const parsed = parseVersion(version);
|
|
203
|
+
const current = parseVersion(VERSION);
|
|
204
|
+
return parsed.major !== current.major;
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressable cache for tool responses.
|
|
3
|
+
* Enables reuse of tool call results and LLM analysis across personas.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Cache entry with metadata.
|
|
7
|
+
*/
|
|
8
|
+
export interface CacheEntry<T> {
|
|
9
|
+
/** The cached value */
|
|
10
|
+
value: T;
|
|
11
|
+
/** When the entry was created */
|
|
12
|
+
createdAt: Date;
|
|
13
|
+
/** When the entry expires */
|
|
14
|
+
expiresAt: Date;
|
|
15
|
+
/** Cache key (hash) */
|
|
16
|
+
key: string;
|
|
17
|
+
/** Human-readable description of what's cached */
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Number of times this entry has been accessed */
|
|
20
|
+
hitCount: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Cache statistics.
|
|
24
|
+
*/
|
|
25
|
+
export interface CacheStats {
|
|
26
|
+
/** Total number of cache hits */
|
|
27
|
+
hits: number;
|
|
28
|
+
/** Total number of cache misses */
|
|
29
|
+
misses: number;
|
|
30
|
+
/** Current number of entries */
|
|
31
|
+
entries: number;
|
|
32
|
+
/** Total bytes used (approximate) */
|
|
33
|
+
sizeBytes: number;
|
|
34
|
+
/** Hit rate as percentage */
|
|
35
|
+
hitRate: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Cache configuration.
|
|
39
|
+
*/
|
|
40
|
+
export interface CacheConfig {
|
|
41
|
+
/** Default TTL in milliseconds (default: 3600000 = 1 hour) */
|
|
42
|
+
defaultTTLMs?: number;
|
|
43
|
+
/** Maximum number of entries (default: 1000) */
|
|
44
|
+
maxEntries?: number;
|
|
45
|
+
/** Maximum total size in bytes (default: 50MB) */
|
|
46
|
+
maxSizeBytes?: number;
|
|
47
|
+
/** Whether to enable cache (default: true) */
|
|
48
|
+
enabled?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* In-memory content-addressable cache.
|
|
52
|
+
*/
|
|
53
|
+
export declare class ResponseCache {
|
|
54
|
+
private cache;
|
|
55
|
+
private config;
|
|
56
|
+
private stats;
|
|
57
|
+
private totalSizeBytes;
|
|
58
|
+
constructor(config?: CacheConfig);
|
|
59
|
+
/**
|
|
60
|
+
* Generate a cache key from input data.
|
|
61
|
+
*/
|
|
62
|
+
generateKey(...parts: unknown[]): string;
|
|
63
|
+
/**
|
|
64
|
+
* Get an entry from cache.
|
|
65
|
+
*/
|
|
66
|
+
get<T>(key: string): T | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Set an entry in cache.
|
|
69
|
+
*/
|
|
70
|
+
set<T>(key: string, value: T, options?: {
|
|
71
|
+
ttlMs?: number;
|
|
72
|
+
description?: string;
|
|
73
|
+
}): void;
|
|
74
|
+
/**
|
|
75
|
+
* Check if key exists and is not expired.
|
|
76
|
+
*/
|
|
77
|
+
has(key: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Delete an entry.
|
|
80
|
+
*/
|
|
81
|
+
delete(key: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Clear all entries.
|
|
84
|
+
*/
|
|
85
|
+
clear(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Get cache statistics.
|
|
88
|
+
*/
|
|
89
|
+
getStats(): CacheStats;
|
|
90
|
+
/**
|
|
91
|
+
* Get or compute a value.
|
|
92
|
+
*/
|
|
93
|
+
getOrCompute<T>(key: string, compute: () => Promise<T>, options?: {
|
|
94
|
+
ttlMs?: number;
|
|
95
|
+
description?: string;
|
|
96
|
+
}): Promise<T>;
|
|
97
|
+
/**
|
|
98
|
+
* Evict entries if needed to make room.
|
|
99
|
+
*/
|
|
100
|
+
private evictIfNeeded;
|
|
101
|
+
/**
|
|
102
|
+
* Evict the oldest entry (LRU based on creation time).
|
|
103
|
+
*/
|
|
104
|
+
private evictOldest;
|
|
105
|
+
/**
|
|
106
|
+
* Estimate the size of a value in bytes.
|
|
107
|
+
*/
|
|
108
|
+
private estimateSize;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Specialized cache for tool responses.
|
|
112
|
+
*/
|
|
113
|
+
export declare class ToolResponseCache extends ResponseCache {
|
|
114
|
+
/**
|
|
115
|
+
* Generate key for a tool call.
|
|
116
|
+
*/
|
|
117
|
+
toolCallKey(toolName: string, args: Record<string, unknown>): string;
|
|
118
|
+
/**
|
|
119
|
+
* Get cached tool response.
|
|
120
|
+
*/
|
|
121
|
+
getToolResponse<T>(toolName: string, args: Record<string, unknown>): T | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* Cache a tool response.
|
|
124
|
+
*/
|
|
125
|
+
setToolResponse<T>(toolName: string, args: Record<string, unknown>, response: T, ttlMs?: number): void;
|
|
126
|
+
/**
|
|
127
|
+
* Generate key for LLM analysis.
|
|
128
|
+
*/
|
|
129
|
+
analysisKey(toolName: string, args: Record<string, unknown>, responseHash: string): string;
|
|
130
|
+
/**
|
|
131
|
+
* Get cached analysis.
|
|
132
|
+
*/
|
|
133
|
+
getAnalysis(toolName: string, args: Record<string, unknown>, responseHash: string): string | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* Cache an analysis.
|
|
136
|
+
*/
|
|
137
|
+
setAnalysis(toolName: string, args: Record<string, unknown>, responseHash: string, analysis: string, ttlMs?: number): void;
|
|
138
|
+
/**
|
|
139
|
+
* Hash a response for use in analysis key.
|
|
140
|
+
*/
|
|
141
|
+
hashResponse(response: unknown): string;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get or create the global cache instance.
|
|
145
|
+
*/
|
|
146
|
+
export declare function getGlobalCache(config?: CacheConfig): ToolResponseCache;
|
|
147
|
+
/**
|
|
148
|
+
* Reset the global cache (for testing).
|
|
149
|
+
*/
|
|
150
|
+
export declare function resetGlobalCache(): void;
|
|
151
|
+
//# sourceMappingURL=response-cache.d.ts.map
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressable cache for tool responses.
|
|
3
|
+
* Enables reuse of tool call results and LLM analysis across personas.
|
|
4
|
+
*/
|
|
5
|
+
import { createHash } from 'crypto';
|
|
6
|
+
import { getLogger } from '../logging/logger.js';
|
|
7
|
+
import { TIME_CONSTANTS, CACHE } from '../constants.js';
|
|
8
|
+
const logger = getLogger('response-cache');
|
|
9
|
+
/**
|
|
10
|
+
* In-memory content-addressable cache.
|
|
11
|
+
*/
|
|
12
|
+
export class ResponseCache {
|
|
13
|
+
cache = new Map();
|
|
14
|
+
config;
|
|
15
|
+
stats = {
|
|
16
|
+
hits: 0,
|
|
17
|
+
misses: 0,
|
|
18
|
+
evictions: 0,
|
|
19
|
+
};
|
|
20
|
+
totalSizeBytes = 0;
|
|
21
|
+
constructor(config = {}) {
|
|
22
|
+
this.config = {
|
|
23
|
+
defaultTTLMs: config.defaultTTLMs ?? TIME_CONSTANTS.DEFAULT_CACHE_TTL,
|
|
24
|
+
maxEntries: config.maxEntries ?? CACHE.MAX_ENTRIES,
|
|
25
|
+
maxSizeBytes: config.maxSizeBytes ?? 50 * 1024 * 1024, // 50MB
|
|
26
|
+
enabled: config.enabled ?? true,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate a cache key from input data.
|
|
31
|
+
*/
|
|
32
|
+
generateKey(...parts) {
|
|
33
|
+
const serialized = parts.map((p) => {
|
|
34
|
+
if (typeof p === 'string')
|
|
35
|
+
return p;
|
|
36
|
+
if (typeof p === 'undefined')
|
|
37
|
+
return 'undefined';
|
|
38
|
+
if (p === null)
|
|
39
|
+
return 'null';
|
|
40
|
+
try {
|
|
41
|
+
return JSON.stringify(p, Object.keys(p).sort());
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return String(p);
|
|
45
|
+
}
|
|
46
|
+
}).join('|');
|
|
47
|
+
return createHash('sha256').update(serialized).digest('hex').slice(0, 16);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get an entry from cache.
|
|
51
|
+
*/
|
|
52
|
+
get(key) {
|
|
53
|
+
if (!this.config.enabled) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
const entry = this.cache.get(key);
|
|
57
|
+
if (!entry) {
|
|
58
|
+
this.stats.misses++;
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
// Check expiration
|
|
62
|
+
if (new Date() > entry.expiresAt) {
|
|
63
|
+
this.delete(key);
|
|
64
|
+
this.stats.misses++;
|
|
65
|
+
logger.debug({ key }, 'Cache entry expired');
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
entry.hitCount++;
|
|
69
|
+
this.stats.hits++;
|
|
70
|
+
logger.debug({ key, hitCount: entry.hitCount }, 'Cache hit');
|
|
71
|
+
return entry.value;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Set an entry in cache.
|
|
75
|
+
*/
|
|
76
|
+
set(key, value, options) {
|
|
77
|
+
if (!this.config.enabled) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const ttl = options?.ttlMs ?? this.config.defaultTTLMs;
|
|
81
|
+
const now = new Date();
|
|
82
|
+
// Calculate entry size
|
|
83
|
+
const entrySize = this.estimateSize(value);
|
|
84
|
+
// Evict if necessary
|
|
85
|
+
this.evictIfNeeded(entrySize);
|
|
86
|
+
const entry = {
|
|
87
|
+
value,
|
|
88
|
+
createdAt: now,
|
|
89
|
+
expiresAt: new Date(now.getTime() + ttl),
|
|
90
|
+
key,
|
|
91
|
+
description: options?.description,
|
|
92
|
+
hitCount: 0,
|
|
93
|
+
};
|
|
94
|
+
// Update size tracking
|
|
95
|
+
const existingEntry = this.cache.get(key);
|
|
96
|
+
if (existingEntry) {
|
|
97
|
+
this.totalSizeBytes -= this.estimateSize(existingEntry.value);
|
|
98
|
+
}
|
|
99
|
+
this.totalSizeBytes += entrySize;
|
|
100
|
+
this.cache.set(key, entry);
|
|
101
|
+
logger.debug({ key, ttlMs: ttl, description: options?.description }, 'Cache entry set');
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Check if key exists and is not expired.
|
|
105
|
+
*/
|
|
106
|
+
has(key) {
|
|
107
|
+
if (!this.config.enabled) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
const entry = this.cache.get(key);
|
|
111
|
+
if (!entry) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (new Date() > entry.expiresAt) {
|
|
115
|
+
this.delete(key);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Delete an entry.
|
|
122
|
+
*/
|
|
123
|
+
delete(key) {
|
|
124
|
+
const entry = this.cache.get(key);
|
|
125
|
+
if (entry) {
|
|
126
|
+
this.totalSizeBytes -= this.estimateSize(entry.value);
|
|
127
|
+
this.cache.delete(key);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Clear all entries.
|
|
134
|
+
*/
|
|
135
|
+
clear() {
|
|
136
|
+
this.cache.clear();
|
|
137
|
+
this.totalSizeBytes = 0;
|
|
138
|
+
logger.debug('Cache cleared');
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get cache statistics.
|
|
142
|
+
*/
|
|
143
|
+
getStats() {
|
|
144
|
+
const total = this.stats.hits + this.stats.misses;
|
|
145
|
+
return {
|
|
146
|
+
hits: this.stats.hits,
|
|
147
|
+
misses: this.stats.misses,
|
|
148
|
+
entries: this.cache.size,
|
|
149
|
+
sizeBytes: this.totalSizeBytes,
|
|
150
|
+
hitRate: total > 0 ? (this.stats.hits / total) * 100 : 0,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get or compute a value.
|
|
155
|
+
*/
|
|
156
|
+
async getOrCompute(key, compute, options) {
|
|
157
|
+
const cached = this.get(key);
|
|
158
|
+
if (cached !== undefined) {
|
|
159
|
+
return cached;
|
|
160
|
+
}
|
|
161
|
+
const value = await compute();
|
|
162
|
+
this.set(key, value, options);
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Evict entries if needed to make room.
|
|
167
|
+
*/
|
|
168
|
+
evictIfNeeded(newEntrySize) {
|
|
169
|
+
// Check entry count
|
|
170
|
+
while (this.cache.size >= this.config.maxEntries) {
|
|
171
|
+
this.evictOldest();
|
|
172
|
+
}
|
|
173
|
+
// Check size
|
|
174
|
+
while (this.totalSizeBytes + newEntrySize > this.config.maxSizeBytes &&
|
|
175
|
+
this.cache.size > 0) {
|
|
176
|
+
this.evictOldest();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Evict the oldest entry (LRU based on creation time).
|
|
181
|
+
*/
|
|
182
|
+
evictOldest() {
|
|
183
|
+
let oldestKey;
|
|
184
|
+
let oldestTime = Infinity;
|
|
185
|
+
for (const [key, entry] of this.cache) {
|
|
186
|
+
const time = entry.createdAt.getTime();
|
|
187
|
+
if (time < oldestTime) {
|
|
188
|
+
oldestTime = time;
|
|
189
|
+
oldestKey = key;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (oldestKey) {
|
|
193
|
+
this.delete(oldestKey);
|
|
194
|
+
this.stats.evictions++;
|
|
195
|
+
logger.debug({ key: oldestKey }, 'Evicted cache entry');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Estimate the size of a value in bytes.
|
|
200
|
+
*/
|
|
201
|
+
estimateSize(value) {
|
|
202
|
+
try {
|
|
203
|
+
return JSON.stringify(value).length * 2; // Approximate UTF-16 size
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return 1000; // Default estimate for non-serializable values
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Specialized cache for tool responses.
|
|
212
|
+
*/
|
|
213
|
+
export class ToolResponseCache extends ResponseCache {
|
|
214
|
+
/**
|
|
215
|
+
* Generate key for a tool call.
|
|
216
|
+
*/
|
|
217
|
+
toolCallKey(toolName, args) {
|
|
218
|
+
return this.generateKey('tool', toolName, args);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Get cached tool response.
|
|
222
|
+
*/
|
|
223
|
+
getToolResponse(toolName, args) {
|
|
224
|
+
const key = this.toolCallKey(toolName, args);
|
|
225
|
+
return this.get(key);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Cache a tool response.
|
|
229
|
+
*/
|
|
230
|
+
setToolResponse(toolName, args, response, ttlMs) {
|
|
231
|
+
const key = this.toolCallKey(toolName, args);
|
|
232
|
+
this.set(key, response, {
|
|
233
|
+
ttlMs,
|
|
234
|
+
description: `Tool: ${toolName}`,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Generate key for LLM analysis.
|
|
239
|
+
*/
|
|
240
|
+
analysisKey(toolName, args, responseHash) {
|
|
241
|
+
return this.generateKey('analysis', toolName, args, responseHash);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get cached analysis.
|
|
245
|
+
*/
|
|
246
|
+
getAnalysis(toolName, args, responseHash) {
|
|
247
|
+
const key = this.analysisKey(toolName, args, responseHash);
|
|
248
|
+
return this.get(key);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Cache an analysis.
|
|
252
|
+
*/
|
|
253
|
+
setAnalysis(toolName, args, responseHash, analysis, ttlMs) {
|
|
254
|
+
const key = this.analysisKey(toolName, args, responseHash);
|
|
255
|
+
this.set(key, analysis, {
|
|
256
|
+
ttlMs,
|
|
257
|
+
description: `Analysis: ${toolName}`,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Hash a response for use in analysis key.
|
|
262
|
+
*/
|
|
263
|
+
hashResponse(response) {
|
|
264
|
+
return this.generateKey('response', response);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Global cache instance for sharing across modules.
|
|
269
|
+
*/
|
|
270
|
+
let globalCache;
|
|
271
|
+
/**
|
|
272
|
+
* Get or create the global cache instance.
|
|
273
|
+
*/
|
|
274
|
+
export function getGlobalCache(config) {
|
|
275
|
+
if (!globalCache) {
|
|
276
|
+
globalCache = new ToolResponseCache(config);
|
|
277
|
+
}
|
|
278
|
+
return globalCache;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Reset the global cache (for testing).
|
|
282
|
+
*/
|
|
283
|
+
export function resetGlobalCache() {
|
|
284
|
+
globalCache?.clear();
|
|
285
|
+
globalCache = undefined;
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=response-cache.js.map
|