c972392b78
IAIService: + generateMatchExplanation, summarizeTradeOffs, generateDataQualitySummary, classifyMarketSignal (4 new methods covering all documented AI output types) OpenRouterAIService: - All 11 methods now make real API calls via withFallback() pattern - Every fallback is explicit (console.warn/error) — no silent mock bleed-through - Proper JSON extraction with type-safe parsers, no any casts - parseNeed: AI JSON → ParseNeedResult mapping (no TODO stubs) - generateFollowUpQuestions, generateMatchExplanation, summarizeTradeOffs, generateDataQualitySummary, classifyMarketSignal, generateOfferEmail, extractCriteria, generateFollowUp: fully implemented Prompts: +followUpQuestionsPrompt, +tradeOffPrompt, +dataQualityPrompt, +marketSignalPrompt Factory (index.ts): - VITE_AI_PROVIDER=mock|openrouter (new, takes priority) - VITE_USE_REAL_AI=true still supported (legacy compat) - Missing API key → explicit console.warn + MockAIService fallback Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
45 lines
1.7 KiB
TypeScript
45 lines
1.7 KiB
TypeScript
/**
|
|
* AI Service Factory
|
|
*
|
|
* Provider selection (priority order):
|
|
* 1. VITE_AI_PROVIDER=openrouter → OpenRouterAIService (requires VITE_OPENROUTER_API_KEY)
|
|
* 2. VITE_AI_PROVIDER=mock → MockAIService (deterministic, no API key required)
|
|
* 3. VITE_USE_REAL_AI=true → OpenRouterAIService (legacy flag, requires VITE_OPENROUTER_API_KEY)
|
|
* 4. (default) → MockAIService
|
|
*
|
|
* If VITE_AI_PROVIDER=openrouter but VITE_OPENROUTER_API_KEY is missing, the factory
|
|
* logs a warning and falls back to MockAIService — never silently fails.
|
|
*
|
|
* Optional: VITE_OPENROUTER_MODEL controls which model OpenRouter uses.
|
|
* Default: anthropic/claude-3-5-haiku
|
|
*/
|
|
import { MockAIService } from './mock/MockAIService'
|
|
import { OpenRouterAIService } from './openrouter/OpenRouterAIService'
|
|
import type { IAIService } from './IAIService'
|
|
|
|
function resolveProvider(): IAIService {
|
|
const provider = import.meta.env.VITE_AI_PROVIDER as string | undefined
|
|
const legacyRealAI = import.meta.env.VITE_USE_REAL_AI === 'true'
|
|
const apiKey = import.meta.env.VITE_OPENROUTER_API_KEY as string | undefined
|
|
|
|
const wantsOpenRouter = provider === 'openrouter' || (legacyRealAI && !provider)
|
|
|
|
if (wantsOpenRouter) {
|
|
if (!apiKey) {
|
|
console.warn(
|
|
'[aiService] OpenRouter selected but VITE_OPENROUTER_API_KEY is missing — falling back to MockAIService.',
|
|
'Set VITE_AI_PROVIDER=mock to suppress this warning.',
|
|
)
|
|
return MockAIService
|
|
}
|
|
return OpenRouterAIService
|
|
}
|
|
|
|
return MockAIService
|
|
}
|
|
|
|
export const aiService: IAIService = resolveProvider()
|
|
|
|
export { MockAIService, OpenRouterAIService }
|
|
export type { IAIService }
|