qa360 1.4.5 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/commands/ai.d.ts +41 -0
- package/dist/commands/ai.js +499 -0
- package/dist/commands/ask.js +12 -12
- package/dist/commands/coverage.d.ts +8 -0
- package/dist/commands/coverage.js +252 -0
- package/dist/commands/explain.d.ts +27 -0
- package/dist/commands/explain.js +630 -0
- package/dist/commands/flakiness.d.ts +73 -0
- package/dist/commands/flakiness.js +435 -0
- package/dist/commands/generate.d.ts +66 -0
- package/dist/commands/generate.js +438 -0
- package/dist/commands/init.d.ts +56 -9
- package/dist/commands/init.js +217 -10
- package/dist/commands/monitor.d.ts +27 -0
- package/dist/commands/monitor.js +225 -0
- package/dist/commands/ollama.d.ts +40 -0
- package/dist/commands/ollama.js +301 -0
- package/dist/commands/pack.d.ts +37 -9
- package/dist/commands/pack.js +240 -141
- package/dist/commands/regression.d.ts +8 -0
- package/dist/commands/regression.js +340 -0
- package/dist/commands/repair.d.ts +26 -0
- package/dist/commands/repair.js +307 -0
- package/dist/commands/retry.d.ts +43 -0
- package/dist/commands/retry.js +275 -0
- package/dist/commands/run.d.ts +8 -3
- package/dist/commands/run.js +45 -31
- package/dist/commands/slo.d.ts +8 -0
- package/dist/commands/slo.js +327 -0
- package/dist/core/adapters/playwright-native-api.d.ts +183 -0
- package/dist/core/adapters/playwright-native-api.js +461 -0
- package/dist/core/adapters/playwright-ui.d.ts +7 -0
- package/dist/core/adapters/playwright-ui.js +29 -1
- package/dist/core/ai/anthropic-provider.d.ts +50 -0
- package/dist/core/ai/anthropic-provider.js +211 -0
- package/dist/core/ai/deepseek-provider.d.ts +81 -0
- package/dist/core/ai/deepseek-provider.js +254 -0
- package/dist/core/ai/index.d.ts +60 -0
- package/dist/core/ai/index.js +18 -0
- package/dist/core/ai/llm-client.d.ts +45 -0
- package/dist/core/ai/llm-client.js +7 -0
- package/dist/core/ai/mock-provider.d.ts +49 -0
- package/dist/core/ai/mock-provider.js +121 -0
- package/dist/core/ai/ollama-provider.d.ts +78 -0
- package/dist/core/ai/ollama-provider.js +192 -0
- package/dist/core/ai/openai-provider.d.ts +48 -0
- package/dist/core/ai/openai-provider.js +188 -0
- package/dist/core/ai/provider-factory.d.ts +160 -0
- package/dist/core/ai/provider-factory.js +269 -0
- package/dist/core/auth/api-key-provider.d.ts +16 -0
- package/dist/core/auth/api-key-provider.js +63 -0
- package/dist/core/auth/aws-iam-provider.d.ts +35 -0
- package/dist/core/auth/aws-iam-provider.js +177 -0
- package/dist/core/auth/azure-ad-provider.d.ts +15 -0
- package/dist/core/auth/azure-ad-provider.js +99 -0
- package/dist/core/auth/basic-auth-provider.d.ts +26 -0
- package/dist/core/auth/basic-auth-provider.js +111 -0
- package/dist/core/auth/gcp-adc-provider.d.ts +27 -0
- package/dist/core/auth/gcp-adc-provider.js +126 -0
- package/dist/core/auth/index.d.ts +238 -0
- package/dist/core/auth/index.js +82 -0
- package/dist/core/auth/jwt-provider.d.ts +19 -0
- package/dist/core/auth/jwt-provider.js +160 -0
- package/dist/core/auth/manager.d.ts +84 -0
- package/dist/core/auth/manager.js +230 -0
- package/dist/core/auth/oauth2-provider.d.ts +17 -0
- package/dist/core/auth/oauth2-provider.js +114 -0
- package/dist/core/auth/totp-provider.d.ts +31 -0
- package/dist/core/auth/totp-provider.js +134 -0
- package/dist/core/auth/ui-login-provider.d.ts +26 -0
- package/dist/core/auth/ui-login-provider.js +198 -0
- package/dist/core/cache/index.d.ts +7 -0
- package/dist/core/cache/index.js +6 -0
- package/dist/core/cache/lru-cache.d.ts +203 -0
- package/dist/core/cache/lru-cache.js +397 -0
- package/dist/core/coverage/analyzer.d.ts +101 -0
- package/dist/core/coverage/analyzer.js +415 -0
- package/dist/core/coverage/collector.d.ts +74 -0
- package/dist/core/coverage/collector.js +459 -0
- package/dist/core/coverage/config.d.ts +37 -0
- package/dist/core/coverage/config.js +156 -0
- package/dist/core/coverage/index.d.ts +11 -0
- package/dist/core/coverage/index.js +15 -0
- package/dist/core/coverage/types.d.ts +267 -0
- package/dist/core/coverage/types.js +6 -0
- package/dist/core/coverage/vault.d.ts +95 -0
- package/dist/core/coverage/vault.js +405 -0
- package/dist/core/dashboard/assets.d.ts +6 -0
- package/dist/core/dashboard/assets.js +690 -0
- package/dist/core/dashboard/index.d.ts +6 -0
- package/dist/core/dashboard/index.js +5 -0
- package/dist/core/dashboard/server.d.ts +72 -0
- package/dist/core/dashboard/server.js +354 -0
- package/dist/core/dashboard/types.d.ts +70 -0
- package/dist/core/dashboard/types.js +5 -0
- package/dist/core/discoverer/index.d.ts +115 -0
- package/dist/core/discoverer/index.js +250 -0
- package/dist/core/flakiness/index.d.ts +228 -0
- package/dist/core/flakiness/index.js +384 -0
- package/dist/core/generation/code-formatter.d.ts +111 -0
- package/dist/core/generation/code-formatter.js +307 -0
- package/dist/core/generation/code-generator.d.ts +144 -0
- package/dist/core/generation/code-generator.js +293 -0
- package/dist/core/generation/generator.d.ts +40 -0
- package/dist/core/generation/generator.js +76 -0
- package/dist/core/generation/index.d.ts +30 -0
- package/dist/core/generation/index.js +28 -0
- package/dist/core/generation/pack-generator.d.ts +107 -0
- package/dist/core/generation/pack-generator.js +416 -0
- package/dist/core/generation/prompt-builder.d.ts +132 -0
- package/dist/core/generation/prompt-builder.js +672 -0
- package/dist/core/generation/source-analyzer.d.ts +213 -0
- package/dist/core/generation/source-analyzer.js +657 -0
- package/dist/core/generation/test-optimizer.d.ts +117 -0
- package/dist/core/generation/test-optimizer.js +328 -0
- package/dist/core/generation/types.d.ts +214 -0
- package/dist/core/generation/types.js +4 -0
- package/dist/core/index.d.ts +23 -1
- package/dist/core/index.js +39 -0
- package/dist/core/pack/validator.js +31 -1
- package/dist/core/pack-v2/index.d.ts +9 -0
- package/dist/core/pack-v2/index.js +8 -0
- package/dist/core/pack-v2/loader.d.ts +62 -0
- package/dist/core/pack-v2/loader.js +231 -0
- package/dist/core/pack-v2/migrator.d.ts +56 -0
- package/dist/core/pack-v2/migrator.js +455 -0
- package/dist/core/pack-v2/validator.d.ts +61 -0
- package/dist/core/pack-v2/validator.js +577 -0
- package/dist/core/regression/detector.d.ts +107 -0
- package/dist/core/regression/detector.js +497 -0
- package/dist/core/regression/index.d.ts +9 -0
- package/dist/core/regression/index.js +11 -0
- package/dist/core/regression/trend-analyzer.d.ts +102 -0
- package/dist/core/regression/trend-analyzer.js +345 -0
- package/dist/core/regression/types.d.ts +222 -0
- package/dist/core/regression/types.js +7 -0
- package/dist/core/regression/vault.d.ts +87 -0
- package/dist/core/regression/vault.js +289 -0
- package/dist/core/repair/engine/fixer.d.ts +24 -0
- package/dist/core/repair/engine/fixer.js +226 -0
- package/dist/core/repair/engine/suggestion-engine.d.ts +18 -0
- package/dist/core/repair/engine/suggestion-engine.js +187 -0
- package/dist/core/repair/index.d.ts +10 -0
- package/dist/core/repair/index.js +13 -0
- package/dist/core/repair/repairer.d.ts +90 -0
- package/dist/core/repair/repairer.js +284 -0
- package/dist/core/repair/types.d.ts +91 -0
- package/dist/core/repair/types.js +6 -0
- package/dist/core/repair/utils/error-analyzer.d.ts +28 -0
- package/dist/core/repair/utils/error-analyzer.js +264 -0
- package/dist/core/retry/flakiness-integration.d.ts +60 -0
- package/dist/core/retry/flakiness-integration.js +228 -0
- package/dist/core/retry/index.d.ts +14 -0
- package/dist/core/retry/index.js +16 -0
- package/dist/core/retry/retry-engine.d.ts +80 -0
- package/dist/core/retry/retry-engine.js +296 -0
- package/dist/core/retry/types.d.ts +178 -0
- package/dist/core/retry/types.js +52 -0
- package/dist/core/retry/vault.d.ts +77 -0
- package/dist/core/retry/vault.js +304 -0
- package/dist/core/runner/e2e-helpers.d.ts +102 -0
- package/dist/core/runner/e2e-helpers.js +153 -0
- package/dist/core/runner/phase3-runner.d.ts +101 -2
- package/dist/core/runner/phase3-runner.js +559 -24
- package/dist/core/self-healing/assertion-healer.d.ts +97 -0
- package/dist/core/self-healing/assertion-healer.js +371 -0
- package/dist/core/self-healing/engine.d.ts +122 -0
- package/dist/core/self-healing/engine.js +538 -0
- package/dist/core/self-healing/index.d.ts +10 -0
- package/dist/core/self-healing/index.js +11 -0
- package/dist/core/self-healing/selector-healer.d.ts +103 -0
- package/dist/core/self-healing/selector-healer.js +372 -0
- package/dist/core/self-healing/types.d.ts +152 -0
- package/dist/core/self-healing/types.js +6 -0
- package/dist/core/slo/config.d.ts +107 -0
- package/dist/core/slo/config.js +360 -0
- package/dist/core/slo/index.d.ts +11 -0
- package/dist/core/slo/index.js +15 -0
- package/dist/core/slo/sli-calculator.d.ts +92 -0
- package/dist/core/slo/sli-calculator.js +364 -0
- package/dist/core/slo/slo-tracker.d.ts +148 -0
- package/dist/core/slo/slo-tracker.js +379 -0
- package/dist/core/slo/types.d.ts +281 -0
- package/dist/core/slo/types.js +7 -0
- package/dist/core/slo/vault.d.ts +102 -0
- package/dist/core/slo/vault.js +427 -0
- package/dist/core/tui/index.d.ts +7 -0
- package/dist/core/tui/index.js +6 -0
- package/dist/core/tui/monitor.d.ts +92 -0
- package/dist/core/tui/monitor.js +271 -0
- package/dist/core/tui/renderer.d.ts +33 -0
- package/dist/core/tui/renderer.js +218 -0
- package/dist/core/tui/types.d.ts +63 -0
- package/dist/core/tui/types.js +5 -0
- package/dist/core/types/pack-v2.d.ts +425 -0
- package/dist/core/types/pack-v2.js +8 -0
- package/dist/core/vault/index.d.ts +116 -0
- package/dist/core/vault/index.js +400 -5
- package/dist/core/watch/index.d.ts +7 -0
- package/dist/core/watch/index.js +6 -0
- package/dist/core/watch/watch-mode.d.ts +213 -0
- package/dist/core/watch/watch-mode.js +389 -0
- package/dist/index.js +68 -68
- package/dist/utils/config.d.ts +5 -0
- package/dist/utils/config.js +136 -0
- package/package.json +5 -1
- package/dist/core/adapters/playwright-api.d.ts +0 -82
- package/dist/core/adapters/playwright-api.js +0 -264
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Provider Factory
|
|
3
|
+
*
|
|
4
|
+
* Factory pattern for creating LLM providers with automatic fallback.
|
|
5
|
+
* Tries providers in order: Ollama → OpenAI → Anthropic → Mock.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const provider = await createLLMProvider();
|
|
9
|
+
* // Returns first available provider
|
|
10
|
+
*/
|
|
11
|
+
import type { LLMProvider, GenerationRequest, GenerationResponse } from './index.js';
|
|
12
|
+
/**
|
|
13
|
+
* Provider priority order for fallback
|
|
14
|
+
* DeepSeek (best value) → Ollama (local, free) → OpenAI → Anthropic → Mock (always available)
|
|
15
|
+
*/
|
|
16
|
+
export declare const PROVIDER_CHAIN: readonly ["deepseek", "ollama", "openai", "anthropic", "mock"];
|
|
17
|
+
export type ProviderType = typeof PROVIDER_CHAIN[number];
|
|
18
|
+
/**
|
|
19
|
+
* Provider factory configuration
|
|
20
|
+
*/
|
|
21
|
+
export interface ProviderFactoryConfig {
|
|
22
|
+
/**
|
|
23
|
+
* Preferred provider (will be tried first)
|
|
24
|
+
*/
|
|
25
|
+
preferred?: ProviderType;
|
|
26
|
+
/**
|
|
27
|
+
* Ordered list of providers to try (overrides default chain)
|
|
28
|
+
*/
|
|
29
|
+
chain?: ProviderType[];
|
|
30
|
+
/**
|
|
31
|
+
* Skip specific providers
|
|
32
|
+
*/
|
|
33
|
+
skip?: ProviderType[];
|
|
34
|
+
/**
|
|
35
|
+
* Ollama configuration
|
|
36
|
+
*/
|
|
37
|
+
ollama?: {
|
|
38
|
+
baseUrl?: string;
|
|
39
|
+
model?: string;
|
|
40
|
+
timeout?: number;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* OpenAI configuration
|
|
44
|
+
*/
|
|
45
|
+
openai?: {
|
|
46
|
+
apiKey?: string;
|
|
47
|
+
baseURL?: string;
|
|
48
|
+
model?: string;
|
|
49
|
+
timeout?: number;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Anthropic configuration
|
|
53
|
+
*/
|
|
54
|
+
anthropic?: {
|
|
55
|
+
apiKey?: string;
|
|
56
|
+
baseURL?: string;
|
|
57
|
+
model?: string;
|
|
58
|
+
timeout?: number;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* DeepSeek configuration
|
|
62
|
+
*/
|
|
63
|
+
deepseek?: {
|
|
64
|
+
apiKey?: string;
|
|
65
|
+
baseURL?: string;
|
|
66
|
+
model?: string;
|
|
67
|
+
timeout?: number;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Mock configuration
|
|
71
|
+
*/
|
|
72
|
+
mock?: {
|
|
73
|
+
delay?: number;
|
|
74
|
+
responses?: Record<string, string>;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Provider selection result
|
|
79
|
+
*/
|
|
80
|
+
export interface ProviderSelection {
|
|
81
|
+
provider: LLMProvider;
|
|
82
|
+
type: ProviderType;
|
|
83
|
+
reason: string;
|
|
84
|
+
skipped: ProviderType[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Fallback provider that wraps the selected provider
|
|
88
|
+
*/
|
|
89
|
+
export declare class FallbackProvider implements LLMProvider {
|
|
90
|
+
name: string;
|
|
91
|
+
models: string[];
|
|
92
|
+
private readonly provider;
|
|
93
|
+
private readonly providerType;
|
|
94
|
+
constructor(provider: LLMProvider, providerType: ProviderType);
|
|
95
|
+
isAvailable(): Promise<boolean>;
|
|
96
|
+
generate(request: GenerationRequest): Promise<GenerationResponse>;
|
|
97
|
+
stream(request: GenerationRequest): AsyncIterable<string>;
|
|
98
|
+
countTokens(text: string): number;
|
|
99
|
+
/**
|
|
100
|
+
* Get the underlying provider type
|
|
101
|
+
*/
|
|
102
|
+
getProviderType(): ProviderType;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Create LLM provider with automatic fallback
|
|
106
|
+
*
|
|
107
|
+
* Tries providers in order until one is available.
|
|
108
|
+
* Logs which provider was selected and why.
|
|
109
|
+
*/
|
|
110
|
+
export declare function createLLMProvider(config?: ProviderFactoryConfig): Promise<FallbackProvider>;
|
|
111
|
+
/**
|
|
112
|
+
* Get provider availability status for all providers
|
|
113
|
+
*/
|
|
114
|
+
export declare function getProviderStatus(config?: ProviderFactoryConfig): Promise<Record<ProviderType, boolean>>;
|
|
115
|
+
/**
|
|
116
|
+
* Auto-detect best available provider
|
|
117
|
+
* Priority: DeepSeek (best value) → Ollama (free local) → OpenAI → Anthropic → Mock
|
|
118
|
+
*/
|
|
119
|
+
export declare function detectBestProvider(config?: ProviderFactoryConfig): Promise<ProviderType>;
|
|
120
|
+
/**
|
|
121
|
+
* Create the best available provider automatically
|
|
122
|
+
* This is the recommended way to get a provider for most use cases.
|
|
123
|
+
*
|
|
124
|
+
* Selection criteria:
|
|
125
|
+
* 1. DeepSeek - Best value, GPT-4 level at 95% lower cost
|
|
126
|
+
* 2. Ollama - Free, local, privacy-preserving
|
|
127
|
+
* 3. OpenAI - Reliable, widely-used
|
|
128
|
+
* 4. Anthropic - High quality, Claude models
|
|
129
|
+
* 5. Mock - Fallback for testing
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* const provider = await createBest();
|
|
133
|
+
* const response = await provider.generate({
|
|
134
|
+
* prompt: 'Generate tests for login form'
|
|
135
|
+
* });
|
|
136
|
+
*/
|
|
137
|
+
export declare function createBest(config?: ProviderFactoryConfig): Promise<FallbackProvider>;
|
|
138
|
+
/**
|
|
139
|
+
* Get provider information for display
|
|
140
|
+
*/
|
|
141
|
+
export interface ProviderInfo {
|
|
142
|
+
type: ProviderType;
|
|
143
|
+
name: string;
|
|
144
|
+
available: boolean;
|
|
145
|
+
description: string;
|
|
146
|
+
costLevel: 'free' | 'low' | 'medium' | 'high';
|
|
147
|
+
capabilities: string[];
|
|
148
|
+
}
|
|
149
|
+
export declare function getProviderInfo(config?: ProviderFactoryConfig): Promise<ProviderInfo[]>;
|
|
150
|
+
/**
|
|
151
|
+
* Create provider with automatic retry on failure
|
|
152
|
+
*
|
|
153
|
+
* If the selected provider fails, automatically falls back
|
|
154
|
+
* to the next available provider in the chain.
|
|
155
|
+
*/
|
|
156
|
+
export declare function createResilientLLMProvider(config?: ProviderFactoryConfig): Promise<FallbackProvider>;
|
|
157
|
+
/**
|
|
158
|
+
* Quick check if any LLM provider is available
|
|
159
|
+
*/
|
|
160
|
+
export declare function hasAnyProvider(config?: ProviderFactoryConfig): Promise<boolean>;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Provider Factory
|
|
3
|
+
*
|
|
4
|
+
* Factory pattern for creating LLM providers with automatic fallback.
|
|
5
|
+
* Tries providers in order: Ollama → OpenAI → Anthropic → Mock.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const provider = await createLLMProvider();
|
|
9
|
+
* // Returns first available provider
|
|
10
|
+
*/
|
|
11
|
+
import { createOllamaProvider } from './index.js';
|
|
12
|
+
import { createOpenAIProvider } from './openai-provider.js';
|
|
13
|
+
import { createAnthropicProvider } from './anthropic-provider.js';
|
|
14
|
+
import { createDeepSeekProvider } from './deepseek-provider.js';
|
|
15
|
+
import { createStandardMockProvider } from './mock-provider.js';
|
|
16
|
+
/**
|
|
17
|
+
* Provider priority order for fallback
|
|
18
|
+
* DeepSeek (best value) → Ollama (local, free) → OpenAI → Anthropic → Mock (always available)
|
|
19
|
+
*/
|
|
20
|
+
export const PROVIDER_CHAIN = [
|
|
21
|
+
'deepseek',
|
|
22
|
+
'ollama',
|
|
23
|
+
'openai',
|
|
24
|
+
'anthropic',
|
|
25
|
+
'mock'
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Fallback provider that wraps the selected provider
|
|
29
|
+
*/
|
|
30
|
+
export class FallbackProvider {
|
|
31
|
+
name = 'fallback';
|
|
32
|
+
models = [];
|
|
33
|
+
provider;
|
|
34
|
+
providerType;
|
|
35
|
+
constructor(provider, providerType) {
|
|
36
|
+
this.provider = provider;
|
|
37
|
+
this.providerType = providerType;
|
|
38
|
+
this.name = `fallback-${providerType}`;
|
|
39
|
+
this.models = provider.models;
|
|
40
|
+
}
|
|
41
|
+
async isAvailable() {
|
|
42
|
+
return this.provider.isAvailable();
|
|
43
|
+
}
|
|
44
|
+
async generate(request) {
|
|
45
|
+
return this.provider.generate(request);
|
|
46
|
+
}
|
|
47
|
+
async *stream(request) {
|
|
48
|
+
if (this.provider.stream) {
|
|
49
|
+
yield* this.provider.stream(request);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Fallback to generate if stream not supported
|
|
53
|
+
const response = await this.provider.generate(request);
|
|
54
|
+
yield response.content;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
countTokens(text) {
|
|
58
|
+
return this.provider.countTokens(text);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get the underlying provider type
|
|
62
|
+
*/
|
|
63
|
+
getProviderType() {
|
|
64
|
+
return this.providerType;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check availability of a provider without creating it
|
|
69
|
+
*/
|
|
70
|
+
async function checkProviderAvailability(type, config) {
|
|
71
|
+
try {
|
|
72
|
+
switch (type) {
|
|
73
|
+
case 'deepseek':
|
|
74
|
+
return await createDeepSeekProvider(config.deepseek).isAvailable();
|
|
75
|
+
case 'ollama':
|
|
76
|
+
return await createOllamaProvider(config.ollama).isAvailable();
|
|
77
|
+
case 'openai':
|
|
78
|
+
return await createOpenAIProvider(config.openai).isAvailable();
|
|
79
|
+
case 'anthropic':
|
|
80
|
+
return await createAnthropicProvider(config.anthropic).isAvailable();
|
|
81
|
+
case 'mock':
|
|
82
|
+
return true; // Mock is always available
|
|
83
|
+
default:
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create provider instance by type
|
|
93
|
+
*/
|
|
94
|
+
function createProviderByType(type, config) {
|
|
95
|
+
switch (type) {
|
|
96
|
+
case 'deepseek':
|
|
97
|
+
return createDeepSeekProvider(config.deepseek);
|
|
98
|
+
case 'ollama':
|
|
99
|
+
return createOllamaProvider(config.ollama);
|
|
100
|
+
case 'openai':
|
|
101
|
+
return createOpenAIProvider(config.openai);
|
|
102
|
+
case 'anthropic':
|
|
103
|
+
return createAnthropicProvider(config.anthropic);
|
|
104
|
+
case 'mock':
|
|
105
|
+
return createStandardMockProvider();
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unknown provider type: ${type}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Create LLM provider with automatic fallback
|
|
112
|
+
*
|
|
113
|
+
* Tries providers in order until one is available.
|
|
114
|
+
* Logs which provider was selected and why.
|
|
115
|
+
*/
|
|
116
|
+
export async function createLLMProvider(config = {}) {
|
|
117
|
+
const chain = config.chain || PROVIDER_CHAIN;
|
|
118
|
+
const skip = config.skip || [];
|
|
119
|
+
// Build the actual chain to try (respect skip list and preferred order)
|
|
120
|
+
let tryChain = [];
|
|
121
|
+
if (config.preferred && !skip.includes(config.preferred)) {
|
|
122
|
+
// Try preferred first, then the rest
|
|
123
|
+
tryChain = [config.preferred];
|
|
124
|
+
tryChain.push(...chain.filter(p => p !== config.preferred && !skip.includes(p)));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
tryChain = chain.filter(p => !skip.includes(p));
|
|
128
|
+
}
|
|
129
|
+
// Ensure mock is always available as last resort
|
|
130
|
+
if (!tryChain.includes('mock')) {
|
|
131
|
+
tryChain.push('mock');
|
|
132
|
+
}
|
|
133
|
+
const skipped = [];
|
|
134
|
+
// Try each provider in order
|
|
135
|
+
for (const type of tryChain) {
|
|
136
|
+
if (skip.includes(type)) {
|
|
137
|
+
skipped.push(type);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const isAvailable = await checkProviderAvailability(type, config);
|
|
141
|
+
if (isAvailable) {
|
|
142
|
+
const provider = createProviderByType(type, config);
|
|
143
|
+
let reason = `Selected ${type}`;
|
|
144
|
+
if (type === 'mock' && tryChain.length > 1) {
|
|
145
|
+
reason = 'No other providers available, using mock';
|
|
146
|
+
}
|
|
147
|
+
else if (skipped.length > 0) {
|
|
148
|
+
reason = `${type} (skipped: ${skipped.join(', ')})`;
|
|
149
|
+
}
|
|
150
|
+
return new FallbackProvider(provider, type);
|
|
151
|
+
}
|
|
152
|
+
skipped.push(type);
|
|
153
|
+
}
|
|
154
|
+
// Should never reach here since mock is always available
|
|
155
|
+
throw new Error('No LLM provider available (even mock failed)');
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get provider availability status for all providers
|
|
159
|
+
*/
|
|
160
|
+
export async function getProviderStatus(config = {}) {
|
|
161
|
+
const status = {};
|
|
162
|
+
for (const type of PROVIDER_CHAIN) {
|
|
163
|
+
status[type] = await checkProviderAvailability(type, config);
|
|
164
|
+
}
|
|
165
|
+
return status;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Auto-detect best available provider
|
|
169
|
+
* Priority: DeepSeek (best value) → Ollama (free local) → OpenAI → Anthropic → Mock
|
|
170
|
+
*/
|
|
171
|
+
export async function detectBestProvider(config = {}) {
|
|
172
|
+
const status = await getProviderStatus(config);
|
|
173
|
+
// Priority: DeepSeek > Ollama > OpenAI > Anthropic > Mock
|
|
174
|
+
if (status.deepseek)
|
|
175
|
+
return 'deepseek';
|
|
176
|
+
if (status.ollama)
|
|
177
|
+
return 'ollama';
|
|
178
|
+
if (status.openai)
|
|
179
|
+
return 'openai';
|
|
180
|
+
if (status.anthropic)
|
|
181
|
+
return 'anthropic';
|
|
182
|
+
return 'mock';
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create the best available provider automatically
|
|
186
|
+
* This is the recommended way to get a provider for most use cases.
|
|
187
|
+
*
|
|
188
|
+
* Selection criteria:
|
|
189
|
+
* 1. DeepSeek - Best value, GPT-4 level at 95% lower cost
|
|
190
|
+
* 2. Ollama - Free, local, privacy-preserving
|
|
191
|
+
* 3. OpenAI - Reliable, widely-used
|
|
192
|
+
* 4. Anthropic - High quality, Claude models
|
|
193
|
+
* 5. Mock - Fallback for testing
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* const provider = await createBest();
|
|
197
|
+
* const response = await provider.generate({
|
|
198
|
+
* prompt: 'Generate tests for login form'
|
|
199
|
+
* });
|
|
200
|
+
*/
|
|
201
|
+
export async function createBest(config = {}) {
|
|
202
|
+
const providerType = await detectBestProvider(config);
|
|
203
|
+
const provider = createProviderByType(providerType, config);
|
|
204
|
+
return new FallbackProvider(provider, providerType);
|
|
205
|
+
}
|
|
206
|
+
export async function getProviderInfo(config = {}) {
|
|
207
|
+
const status = await getProviderStatus(config);
|
|
208
|
+
return [
|
|
209
|
+
{
|
|
210
|
+
type: 'deepseek',
|
|
211
|
+
name: 'DeepSeek',
|
|
212
|
+
available: status.deepseek,
|
|
213
|
+
description: 'GPT-4 level performance at 95% lower cost',
|
|
214
|
+
costLevel: 'low',
|
|
215
|
+
capabilities: ['code-generation', 'test-generation', 'analysis', 'chat']
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
type: 'ollama',
|
|
219
|
+
name: 'Ollama',
|
|
220
|
+
available: status.ollama,
|
|
221
|
+
description: 'Local LLM inference, 100% free',
|
|
222
|
+
costLevel: 'free',
|
|
223
|
+
capabilities: ['code-generation', 'test-generation', 'offline', 'privacy']
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
type: 'openai',
|
|
227
|
+
name: 'OpenAI',
|
|
228
|
+
available: status.openai,
|
|
229
|
+
description: 'GPT-4, GPT-4 Turbo, reliable API',
|
|
230
|
+
costLevel: 'high',
|
|
231
|
+
capabilities: ['code-generation', 'test-generation', 'analysis', 'chat']
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
type: 'anthropic',
|
|
235
|
+
name: 'Anthropic',
|
|
236
|
+
available: status.anthropic,
|
|
237
|
+
description: 'Claude models, high quality outputs',
|
|
238
|
+
costLevel: 'high',
|
|
239
|
+
capabilities: ['code-generation', 'test-generation', 'analysis', 'chat']
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
type: 'mock',
|
|
243
|
+
name: 'Mock',
|
|
244
|
+
available: true,
|
|
245
|
+
description: 'Mock provider for testing',
|
|
246
|
+
costLevel: 'free',
|
|
247
|
+
capabilities: ['testing', 'mocking']
|
|
248
|
+
}
|
|
249
|
+
];
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Create provider with automatic retry on failure
|
|
253
|
+
*
|
|
254
|
+
* If the selected provider fails, automatically falls back
|
|
255
|
+
* to the next available provider in the chain.
|
|
256
|
+
*/
|
|
257
|
+
export async function createResilientLLMProvider(config = {}) {
|
|
258
|
+
const provider = await createLLMProvider(config);
|
|
259
|
+
// Wrap with retry logic could be added here
|
|
260
|
+
// For now, return the standard fallback provider
|
|
261
|
+
return provider;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Quick check if any LLM provider is available
|
|
265
|
+
*/
|
|
266
|
+
export async function hasAnyProvider(config = {}) {
|
|
267
|
+
const status = await getProviderStatus(config);
|
|
268
|
+
return Object.values(status).some(v => v);
|
|
269
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Key Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles API key authentication with support for:
|
|
5
|
+
* - Custom header names (default: X-API-Key)
|
|
6
|
+
* - Custom prefix (e.g., "Bearer ")
|
|
7
|
+
* - Header or query param location
|
|
8
|
+
*/
|
|
9
|
+
import { AuthProvider, AuthResult, APIKeyAuthConfig } from './index.js';
|
|
10
|
+
export declare class APIKeyProvider implements AuthProvider<APIKeyAuthConfig> {
|
|
11
|
+
readonly type: "api_key";
|
|
12
|
+
authenticate(config: APIKeyAuthConfig): Promise<AuthResult>;
|
|
13
|
+
clear(config: APIKeyAuthConfig): Promise<void>;
|
|
14
|
+
validate(config: APIKeyAuthConfig): Promise<boolean>;
|
|
15
|
+
private getCacheKey;
|
|
16
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Key Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles API key authentication with support for:
|
|
5
|
+
* - Custom header names (default: X-API-Key)
|
|
6
|
+
* - Custom prefix (e.g., "Bearer ")
|
|
7
|
+
* - Header or query param location
|
|
8
|
+
*/
|
|
9
|
+
import { authCache, createCacheKey } from './index.js';
|
|
10
|
+
export class APIKeyProvider {
|
|
11
|
+
type = 'api_key';
|
|
12
|
+
async authenticate(config) {
|
|
13
|
+
const { key, header_name = 'X-API-Key', prefix = '', location = 'header', cache } = config;
|
|
14
|
+
const cacheKey = this.getCacheKey(config);
|
|
15
|
+
// Check cache first
|
|
16
|
+
if (cache?.enabled !== false) {
|
|
17
|
+
const cached = authCache.get(cacheKey);
|
|
18
|
+
if (cached) {
|
|
19
|
+
return { success: true, credentials: cached };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const credentials = {
|
|
23
|
+
type: 'api_key'
|
|
24
|
+
};
|
|
25
|
+
// Prefix is used as-is, no automatic space added
|
|
26
|
+
const fullKey = prefix + key;
|
|
27
|
+
if (location === 'header') {
|
|
28
|
+
credentials.headers = {
|
|
29
|
+
[header_name]: fullKey
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
credentials.queryParams = {
|
|
34
|
+
api_key: fullKey
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// Cache if enabled
|
|
38
|
+
if (cache?.enabled !== false) {
|
|
39
|
+
const ttl = cache?.ttl || 3600;
|
|
40
|
+
authCache.set(cacheKey, credentials, ttl);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
success: true,
|
|
44
|
+
credentials
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async clear(config) {
|
|
48
|
+
const key = this.getCacheKey(config);
|
|
49
|
+
authCache.clear(key);
|
|
50
|
+
}
|
|
51
|
+
async validate(config) {
|
|
52
|
+
const cacheKey = this.getCacheKey(config);
|
|
53
|
+
// Check cache first, then validate key
|
|
54
|
+
if (authCache.has(cacheKey)) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return !!config.key && config.key.length > 0;
|
|
58
|
+
}
|
|
59
|
+
getCacheKey(config) {
|
|
60
|
+
// Use header name as identifier
|
|
61
|
+
return createCacheKey('api_key', config.header_name || 'default');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS IAM Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles AWS authentication using IAM credentials.
|
|
5
|
+
* Supports credential chains, environment variables, and profiles.
|
|
6
|
+
*/
|
|
7
|
+
import { AuthProvider, AuthResult, AWSIamConfig } from './index.js';
|
|
8
|
+
export declare class AWSIamProvider implements AuthProvider<AWSIamConfig> {
|
|
9
|
+
readonly type: "aws_iam";
|
|
10
|
+
authenticate(config: AWSIamConfig): Promise<AuthResult>;
|
|
11
|
+
refresh(config: AWSIamConfig): Promise<AuthResult>;
|
|
12
|
+
clear(config: AWSIamConfig): Promise<void>;
|
|
13
|
+
validate(config: AWSIamConfig): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Get AWS credentials from various sources
|
|
16
|
+
*/
|
|
17
|
+
private getCredentials;
|
|
18
|
+
/**
|
|
19
|
+
* Get credentials from environment variables
|
|
20
|
+
*/
|
|
21
|
+
private getFromEnv;
|
|
22
|
+
/**
|
|
23
|
+
* Get credentials from AWS profile file
|
|
24
|
+
*/
|
|
25
|
+
private getFromProfile;
|
|
26
|
+
/**
|
|
27
|
+
* Get credentials from AWS SDK v3
|
|
28
|
+
*/
|
|
29
|
+
private getFromSDK;
|
|
30
|
+
/**
|
|
31
|
+
* Get AMZ date format for AWS signing
|
|
32
|
+
*/
|
|
33
|
+
private getAmzDate;
|
|
34
|
+
private getCacheKey;
|
|
35
|
+
}
|