@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,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama LLM client implementation for local models.
|
|
3
|
+
*/
|
|
4
|
+
import type { LLMClient, Message, CompletionOptions, ProviderInfo, StreamingOptions, StreamingResult } from './client.js';
|
|
5
|
+
export interface OllamaClientOptions {
|
|
6
|
+
/** Base URL for Ollama API (defaults to http://localhost:11434) */
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
/** Default model to use */
|
|
9
|
+
model?: string;
|
|
10
|
+
/** Callback to receive token usage from each API call */
|
|
11
|
+
onUsage?: (inputTokens: number, outputTokens: number) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Ollama LLM client for local model inference.
|
|
15
|
+
*/
|
|
16
|
+
export declare class OllamaClient implements LLMClient {
|
|
17
|
+
private baseUrl;
|
|
18
|
+
private defaultModel;
|
|
19
|
+
private logger;
|
|
20
|
+
private onUsage?;
|
|
21
|
+
constructor(options?: OllamaClientOptions);
|
|
22
|
+
getProviderInfo(): ProviderInfo;
|
|
23
|
+
chat(messages: Message[], options?: CompletionOptions): Promise<string>;
|
|
24
|
+
complete(prompt: string, options?: CompletionOptions): Promise<string>;
|
|
25
|
+
parseJSON<T>(response: string): T;
|
|
26
|
+
stream(prompt: string, options?: StreamingOptions): Promise<StreamingResult>;
|
|
27
|
+
streamChat(messages: Message[], options?: StreamingOptions): Promise<StreamingResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Check if Ollama is running and accessible.
|
|
30
|
+
*/
|
|
31
|
+
isAvailable(): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* List available models.
|
|
34
|
+
*/
|
|
35
|
+
listModels(): Promise<string[]>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=ollama.d.ts.map
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama LLM client implementation for local models.
|
|
3
|
+
*/
|
|
4
|
+
import { DEFAULT_MODELS, parseJSONResponse } from './client.js';
|
|
5
|
+
import { withRetry, LLM_RETRY_OPTIONS } from '../errors/retry.js';
|
|
6
|
+
import { LLMConnectionError, BellwetherError } from '../errors/index.js';
|
|
7
|
+
import { getLogger } from '../logging/logger.js';
|
|
8
|
+
import { LLM_DEFAULTS } from '../constants.js';
|
|
9
|
+
/**
|
|
10
|
+
* Ollama LLM client for local model inference.
|
|
11
|
+
*/
|
|
12
|
+
export class OllamaClient {
|
|
13
|
+
baseUrl;
|
|
14
|
+
defaultModel;
|
|
15
|
+
logger = getLogger('ollama');
|
|
16
|
+
onUsage;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.baseUrl = options?.baseUrl ?? process.env.OLLAMA_BASE_URL ?? LLM_DEFAULTS.OLLAMA_BASE_URL;
|
|
19
|
+
this.defaultModel = options?.model ?? DEFAULT_MODELS.ollama;
|
|
20
|
+
this.onUsage = options?.onUsage;
|
|
21
|
+
}
|
|
22
|
+
getProviderInfo() {
|
|
23
|
+
return {
|
|
24
|
+
id: 'ollama',
|
|
25
|
+
name: 'Ollama (Local)',
|
|
26
|
+
supportsJSON: true, // Ollama supports format: 'json'
|
|
27
|
+
supportsStreaming: true,
|
|
28
|
+
defaultModel: this.defaultModel,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async chat(messages, options) {
|
|
32
|
+
const model = options?.model ?? this.defaultModel;
|
|
33
|
+
return withRetry(async () => {
|
|
34
|
+
// Build messages array with optional system prompt
|
|
35
|
+
const allMessages = [];
|
|
36
|
+
if (options?.systemPrompt) {
|
|
37
|
+
allMessages.push({
|
|
38
|
+
role: 'system',
|
|
39
|
+
content: options.systemPrompt,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
for (const msg of messages) {
|
|
43
|
+
allMessages.push({
|
|
44
|
+
role: msg.role,
|
|
45
|
+
content: msg.content,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const request = {
|
|
49
|
+
model,
|
|
50
|
+
messages: allMessages,
|
|
51
|
+
stream: false,
|
|
52
|
+
options: {
|
|
53
|
+
temperature: options?.temperature ?? LLM_DEFAULTS.TEMPERATURE,
|
|
54
|
+
num_predict: options?.maxTokens ?? LLM_DEFAULTS.MAX_TOKENS,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
// Add JSON format if requested
|
|
58
|
+
if (options?.responseFormat === 'json') {
|
|
59
|
+
request.format = 'json';
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const response = await fetch(`${this.baseUrl}/api/chat`, {
|
|
63
|
+
method: 'POST',
|
|
64
|
+
headers: {
|
|
65
|
+
'Content-Type': 'application/json',
|
|
66
|
+
},
|
|
67
|
+
body: JSON.stringify(request),
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
const errorText = await response.text();
|
|
71
|
+
throw new Error(`Ollama API error (${response.status}): ${errorText}`);
|
|
72
|
+
}
|
|
73
|
+
const result = await response.json();
|
|
74
|
+
if (!result.message?.content) {
|
|
75
|
+
throw new Error('No content in Ollama response');
|
|
76
|
+
}
|
|
77
|
+
// Track token usage from Ollama response
|
|
78
|
+
if (this.onUsage) {
|
|
79
|
+
const promptTokens = result.prompt_eval_count ?? 0;
|
|
80
|
+
const completionTokens = result.eval_count ?? 0;
|
|
81
|
+
if (promptTokens > 0 || completionTokens > 0) {
|
|
82
|
+
this.onUsage(promptTokens, completionTokens);
|
|
83
|
+
this.logger.debug({
|
|
84
|
+
promptTokens,
|
|
85
|
+
completionTokens,
|
|
86
|
+
msg: 'Ollama token usage tracked',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result.message.content;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (error instanceof Error) {
|
|
94
|
+
const message = error.message.toLowerCase();
|
|
95
|
+
// Check for connection errors - these are retryable
|
|
96
|
+
if (message.includes('econnrefused') || message.includes('fetch failed')) {
|
|
97
|
+
throw new LLMConnectionError('ollama', model, undefined, error);
|
|
98
|
+
}
|
|
99
|
+
// Check for model not found - not retryable
|
|
100
|
+
if (message.includes('not found') || message.includes('does not exist')) {
|
|
101
|
+
throw new BellwetherError(`Model "${model}" not found. Pull it with: ollama pull ${model}`, {
|
|
102
|
+
code: 'LLM_MODEL_NOT_FOUND',
|
|
103
|
+
severity: 'high',
|
|
104
|
+
retryable: 'terminal',
|
|
105
|
+
context: { component: 'ollama', metadata: { model } },
|
|
106
|
+
cause: error,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}, {
|
|
113
|
+
...LLM_RETRY_OPTIONS,
|
|
114
|
+
maxAttempts: 2, // Ollama is local, fewer retries needed
|
|
115
|
+
operation: 'Ollama chat completion',
|
|
116
|
+
context: { component: 'ollama', metadata: { model, baseUrl: this.baseUrl } },
|
|
117
|
+
onRetry: (error, attempt, delayMs) => {
|
|
118
|
+
this.logger.debug({
|
|
119
|
+
attempt,
|
|
120
|
+
delayMs: Math.round(delayMs),
|
|
121
|
+
error: error instanceof Error ? error.message : String(error),
|
|
122
|
+
msg: `Retrying Ollama API call`,
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async complete(prompt, options) {
|
|
128
|
+
return this.chat([{ role: 'user', content: prompt }], options);
|
|
129
|
+
}
|
|
130
|
+
parseJSON(response) {
|
|
131
|
+
return parseJSONResponse(response);
|
|
132
|
+
}
|
|
133
|
+
async stream(prompt, options) {
|
|
134
|
+
return this.streamChat([{ role: 'user', content: prompt }], options);
|
|
135
|
+
}
|
|
136
|
+
async streamChat(messages, options) {
|
|
137
|
+
const model = options?.model ?? this.defaultModel;
|
|
138
|
+
return withRetry(async () => {
|
|
139
|
+
// Build messages array with optional system prompt
|
|
140
|
+
const allMessages = [];
|
|
141
|
+
if (options?.systemPrompt) {
|
|
142
|
+
allMessages.push({
|
|
143
|
+
role: 'system',
|
|
144
|
+
content: options.systemPrompt,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
for (const msg of messages) {
|
|
148
|
+
allMessages.push({
|
|
149
|
+
role: msg.role,
|
|
150
|
+
content: msg.content,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
const request = {
|
|
154
|
+
model,
|
|
155
|
+
messages: allMessages,
|
|
156
|
+
stream: true, // Enable streaming
|
|
157
|
+
options: {
|
|
158
|
+
temperature: options?.temperature ?? LLM_DEFAULTS.TEMPERATURE,
|
|
159
|
+
num_predict: options?.maxTokens ?? LLM_DEFAULTS.MAX_TOKENS,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
// Add JSON format if requested
|
|
163
|
+
if (options?.responseFormat === 'json') {
|
|
164
|
+
request.format = 'json';
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const response = await fetch(`${this.baseUrl}/api/chat`, {
|
|
168
|
+
method: 'POST',
|
|
169
|
+
headers: {
|
|
170
|
+
'Content-Type': 'application/json',
|
|
171
|
+
},
|
|
172
|
+
body: JSON.stringify(request),
|
|
173
|
+
});
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
const errorText = await response.text();
|
|
176
|
+
throw new Error(`Ollama API error (${response.status}): ${errorText}`);
|
|
177
|
+
}
|
|
178
|
+
if (!response.body) {
|
|
179
|
+
throw new Error('No response body for streaming');
|
|
180
|
+
}
|
|
181
|
+
// Read the NDJSON stream
|
|
182
|
+
const reader = response.body.getReader();
|
|
183
|
+
const decoder = new TextDecoder();
|
|
184
|
+
let fullText = '';
|
|
185
|
+
let promptTokens = 0;
|
|
186
|
+
let completionTokens = 0;
|
|
187
|
+
let buffer = '';
|
|
188
|
+
try {
|
|
189
|
+
let done = false;
|
|
190
|
+
while (!done) {
|
|
191
|
+
const result = await reader.read();
|
|
192
|
+
done = result.done;
|
|
193
|
+
const value = result.value;
|
|
194
|
+
if (done)
|
|
195
|
+
break;
|
|
196
|
+
// Decode chunk and add to buffer
|
|
197
|
+
buffer += decoder.decode(value, { stream: true });
|
|
198
|
+
// Process complete lines (NDJSON format)
|
|
199
|
+
const lines = buffer.split('\n');
|
|
200
|
+
buffer = lines.pop() ?? ''; // Keep incomplete line in buffer
|
|
201
|
+
for (const line of lines) {
|
|
202
|
+
if (!line.trim())
|
|
203
|
+
continue;
|
|
204
|
+
try {
|
|
205
|
+
const chunk = JSON.parse(line);
|
|
206
|
+
if (chunk.message?.content) {
|
|
207
|
+
fullText += chunk.message.content;
|
|
208
|
+
options?.onChunk?.(chunk.message.content);
|
|
209
|
+
}
|
|
210
|
+
// Track token counts from final chunk
|
|
211
|
+
if (chunk.done) {
|
|
212
|
+
promptTokens = chunk.prompt_eval_count ?? 0;
|
|
213
|
+
completionTokens = chunk.eval_count ?? 0;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// Skip malformed JSON lines
|
|
218
|
+
this.logger.debug({ line }, 'Skipping malformed stream line');
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Process any remaining buffer
|
|
223
|
+
if (buffer.trim()) {
|
|
224
|
+
try {
|
|
225
|
+
const chunk = JSON.parse(buffer);
|
|
226
|
+
if (chunk.message?.content) {
|
|
227
|
+
fullText += chunk.message.content;
|
|
228
|
+
options?.onChunk?.(chunk.message.content);
|
|
229
|
+
}
|
|
230
|
+
if (chunk.done) {
|
|
231
|
+
promptTokens = chunk.prompt_eval_count ?? 0;
|
|
232
|
+
completionTokens = chunk.eval_count ?? 0;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch (parseError) {
|
|
236
|
+
// Log parse error for debugging
|
|
237
|
+
this.logger.debug({ buffer, error: parseError instanceof Error ? parseError.message : String(parseError) }, 'Failed to parse final buffer chunk');
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
reader.releaseLock();
|
|
243
|
+
}
|
|
244
|
+
// Track token usage
|
|
245
|
+
if (this.onUsage && (promptTokens > 0 || completionTokens > 0)) {
|
|
246
|
+
this.onUsage(promptTokens, completionTokens);
|
|
247
|
+
this.logger.debug({
|
|
248
|
+
promptTokens,
|
|
249
|
+
completionTokens,
|
|
250
|
+
msg: 'Ollama streaming token usage tracked',
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
if (!fullText) {
|
|
254
|
+
throw new Error('No content in Ollama streaming response');
|
|
255
|
+
}
|
|
256
|
+
options?.onComplete?.(fullText);
|
|
257
|
+
return { text: fullText, completed: true };
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
options?.onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
261
|
+
if (error instanceof Error) {
|
|
262
|
+
const message = error.message.toLowerCase();
|
|
263
|
+
// Check for connection errors - these are retryable
|
|
264
|
+
if (message.includes('econnrefused') || message.includes('fetch failed')) {
|
|
265
|
+
throw new LLMConnectionError('ollama', model, undefined, error);
|
|
266
|
+
}
|
|
267
|
+
// Check for model not found - not retryable
|
|
268
|
+
if (message.includes('not found') || message.includes('does not exist')) {
|
|
269
|
+
throw new BellwetherError(`Model "${model}" not found. Pull it with: ollama pull ${model}`, {
|
|
270
|
+
code: 'LLM_MODEL_NOT_FOUND',
|
|
271
|
+
severity: 'high',
|
|
272
|
+
retryable: 'terminal',
|
|
273
|
+
context: { component: 'ollama', metadata: { model } },
|
|
274
|
+
cause: error,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
throw error;
|
|
279
|
+
}
|
|
280
|
+
}, {
|
|
281
|
+
...LLM_RETRY_OPTIONS,
|
|
282
|
+
maxAttempts: 2, // Ollama is local, fewer retries needed
|
|
283
|
+
operation: 'Ollama streaming chat completion',
|
|
284
|
+
context: { component: 'ollama', metadata: { model, baseUrl: this.baseUrl } },
|
|
285
|
+
onRetry: (error, attempt, delayMs) => {
|
|
286
|
+
this.logger.debug({
|
|
287
|
+
attempt,
|
|
288
|
+
delayMs: Math.round(delayMs),
|
|
289
|
+
error: error instanceof Error ? error.message : String(error),
|
|
290
|
+
msg: `Retrying Ollama streaming API call`,
|
|
291
|
+
});
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Check if Ollama is running and accessible.
|
|
297
|
+
*/
|
|
298
|
+
async isAvailable() {
|
|
299
|
+
try {
|
|
300
|
+
const response = await fetch(`${this.baseUrl}/api/tags`, {
|
|
301
|
+
method: 'GET',
|
|
302
|
+
});
|
|
303
|
+
return response.ok;
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
this.logger.debug({ error: error instanceof Error ? error.message : String(error) }, 'Ollama availability check failed');
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* List available models.
|
|
312
|
+
*/
|
|
313
|
+
async listModels() {
|
|
314
|
+
try {
|
|
315
|
+
const response = await fetch(`${this.baseUrl}/api/tags`, {
|
|
316
|
+
method: 'GET',
|
|
317
|
+
});
|
|
318
|
+
if (!response.ok) {
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
const result = await response.json();
|
|
322
|
+
return result.models?.map(m => m.name) ?? [];
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
this.logger.debug({ error: error instanceof Error ? error.message : String(error) }, 'Failed to list Ollama models');
|
|
326
|
+
return [];
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { LLMClient, Message, CompletionOptions, ProviderInfo, StreamingOptions, StreamingResult } from './client.js';
|
|
2
|
+
export interface OpenAIClientOptions {
|
|
3
|
+
/** API key (defaults to OPENAI_API_KEY env var) */
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
/** Default model to use */
|
|
6
|
+
model?: string;
|
|
7
|
+
/** Base URL for API (for proxies/alternatives) */
|
|
8
|
+
baseURL?: string;
|
|
9
|
+
/** Callback to receive token usage from each API call */
|
|
10
|
+
onUsage?: (inputTokens: number, outputTokens: number) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare class OpenAIClient implements LLMClient {
|
|
13
|
+
private client;
|
|
14
|
+
private defaultModel;
|
|
15
|
+
private logger;
|
|
16
|
+
private onUsage?;
|
|
17
|
+
constructor(options?: OpenAIClientOptions);
|
|
18
|
+
getProviderInfo(): ProviderInfo;
|
|
19
|
+
chat(messages: Message[], options?: CompletionOptions): Promise<string>;
|
|
20
|
+
complete(prompt: string, options?: CompletionOptions): Promise<string>;
|
|
21
|
+
parseJSON<T>(response: string): T;
|
|
22
|
+
stream(prompt: string, options?: StreamingOptions): Promise<StreamingResult>;
|
|
23
|
+
streamChat(messages: Message[], options?: StreamingOptions): Promise<StreamingResult>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=openai.d.ts.map
|