@tpitre/story-ui 2.2.0 → 2.3.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/.env.sample +82 -11
- package/README.md +89 -0
- package/dist/cli/deploy.d.ts +17 -0
- package/dist/cli/deploy.d.ts.map +1 -0
- package/dist/cli/deploy.js +696 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +26 -2
- package/dist/cli/setup.d.ts +11 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +437 -110
- package/dist/mcp-server/index.d.ts +2 -0
- package/dist/mcp-server/index.d.ts.map +1 -0
- package/dist/mcp-server/index.js +120 -2
- package/dist/mcp-server/mcp-stdio-server.d.ts +3 -0
- package/dist/mcp-server/mcp-stdio-server.d.ts.map +1 -0
- package/dist/mcp-server/mcp-stdio-server.js +8 -1
- package/dist/mcp-server/routes/claude.d.ts +3 -0
- package/dist/mcp-server/routes/claude.d.ts.map +1 -0
- package/dist/mcp-server/routes/claude.js +60 -23
- package/dist/mcp-server/routes/components.d.ts +4 -0
- package/dist/mcp-server/routes/components.d.ts.map +1 -0
- package/dist/mcp-server/routes/frameworks.d.ts +38 -0
- package/dist/mcp-server/routes/frameworks.d.ts.map +1 -0
- package/dist/mcp-server/routes/frameworks.js +183 -0
- package/dist/mcp-server/routes/generateStory.d.ts +3 -0
- package/dist/mcp-server/routes/generateStory.d.ts.map +1 -0
- package/dist/mcp-server/routes/generateStory.js +160 -76
- package/dist/mcp-server/routes/generateStoryStream.d.ts +12 -0
- package/dist/mcp-server/routes/generateStoryStream.d.ts.map +1 -0
- package/dist/mcp-server/routes/generateStoryStream.js +947 -0
- package/dist/mcp-server/routes/hybridStories.d.ts +18 -0
- package/dist/mcp-server/routes/hybridStories.d.ts.map +1 -0
- package/dist/mcp-server/routes/mcpRemote.d.ts +14 -0
- package/dist/mcp-server/routes/mcpRemote.d.ts.map +1 -0
- package/dist/mcp-server/routes/mcpRemote.js +489 -0
- package/dist/mcp-server/routes/memoryStories.d.ts +26 -0
- package/dist/mcp-server/routes/memoryStories.d.ts.map +1 -0
- package/dist/mcp-server/routes/providers.d.ts +89 -0
- package/dist/mcp-server/routes/providers.d.ts.map +1 -0
- package/dist/mcp-server/routes/providers.js +369 -0
- package/dist/mcp-server/routes/storySync.d.ts +26 -0
- package/dist/mcp-server/routes/storySync.d.ts.map +1 -0
- package/dist/mcp-server/routes/streamTypes.d.ts +110 -0
- package/dist/mcp-server/routes/streamTypes.d.ts.map +1 -0
- package/dist/mcp-server/routes/streamTypes.js +18 -0
- package/dist/mcp-server/sessionManager.d.ts +50 -0
- package/dist/mcp-server/sessionManager.d.ts.map +1 -0
- package/dist/story-generator/componentBlacklist.d.ts +21 -0
- package/dist/story-generator/componentBlacklist.d.ts.map +1 -0
- package/dist/story-generator/componentDiscovery.d.ts +28 -0
- package/dist/story-generator/componentDiscovery.d.ts.map +1 -0
- package/dist/story-generator/componentRegistryGenerator.d.ts +49 -0
- package/dist/story-generator/componentRegistryGenerator.d.ts.map +1 -0
- package/dist/story-generator/componentRegistryGenerator.js +205 -0
- package/dist/story-generator/configLoader.d.ts +33 -0
- package/dist/story-generator/configLoader.d.ts.map +1 -0
- package/dist/story-generator/considerationsLoader.d.ts +32 -0
- package/dist/story-generator/considerationsLoader.d.ts.map +1 -0
- package/dist/story-generator/documentation-sources.d.ts +28 -0
- package/dist/story-generator/documentation-sources.d.ts.map +1 -0
- package/dist/story-generator/documentationLoader.d.ts +64 -0
- package/dist/story-generator/documentationLoader.d.ts.map +1 -0
- package/dist/story-generator/dynamicPackageDiscovery.d.ts +97 -0
- package/dist/story-generator/dynamicPackageDiscovery.d.ts.map +1 -0
- package/dist/story-generator/enhancedComponentDiscovery.d.ts +125 -0
- package/dist/story-generator/enhancedComponentDiscovery.d.ts.map +1 -0
- package/dist/story-generator/enhancedComponentDiscovery.js +111 -11
- package/dist/story-generator/framework-adapters/angular-adapter.d.ts +40 -0
- package/dist/story-generator/framework-adapters/angular-adapter.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/angular-adapter.js +427 -0
- package/dist/story-generator/framework-adapters/base-adapter.d.ts +75 -0
- package/dist/story-generator/framework-adapters/base-adapter.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/base-adapter.js +147 -0
- package/dist/story-generator/framework-adapters/framework-detector.d.ts +55 -0
- package/dist/story-generator/framework-adapters/framework-detector.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/framework-detector.js +323 -0
- package/dist/story-generator/framework-adapters/index.d.ts +97 -0
- package/dist/story-generator/framework-adapters/index.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/index.js +198 -0
- package/dist/story-generator/framework-adapters/react-adapter.d.ts +40 -0
- package/dist/story-generator/framework-adapters/react-adapter.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/react-adapter.js +316 -0
- package/dist/story-generator/framework-adapters/svelte-adapter.d.ts +40 -0
- package/dist/story-generator/framework-adapters/svelte-adapter.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/svelte-adapter.js +372 -0
- package/dist/story-generator/framework-adapters/types.d.ts +182 -0
- package/dist/story-generator/framework-adapters/types.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/types.js +8 -0
- package/dist/story-generator/framework-adapters/vue-adapter.d.ts +36 -0
- package/dist/story-generator/framework-adapters/vue-adapter.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/vue-adapter.js +336 -0
- package/dist/story-generator/framework-adapters/web-components-adapter.d.ts +54 -0
- package/dist/story-generator/framework-adapters/web-components-adapter.d.ts.map +1 -0
- package/dist/story-generator/framework-adapters/web-components-adapter.js +387 -0
- package/dist/story-generator/generateStory.d.ts +7 -0
- package/dist/story-generator/generateStory.d.ts.map +1 -0
- package/dist/story-generator/gitignoreManager.d.ts +50 -0
- package/dist/story-generator/gitignoreManager.d.ts.map +1 -0
- package/dist/story-generator/imageProcessor.d.ts +80 -0
- package/dist/story-generator/imageProcessor.d.ts.map +1 -0
- package/dist/story-generator/imageProcessor.js +391 -0
- package/dist/story-generator/inMemoryStoryService.d.ts +89 -0
- package/dist/story-generator/inMemoryStoryService.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/base-provider.d.ts +36 -0
- package/dist/story-generator/llm-providers/base-provider.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/base-provider.js +135 -0
- package/dist/story-generator/llm-providers/claude-provider.d.ts +23 -0
- package/dist/story-generator/llm-providers/claude-provider.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/claude-provider.js +414 -0
- package/dist/story-generator/llm-providers/gemini-provider.d.ts +24 -0
- package/dist/story-generator/llm-providers/gemini-provider.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/gemini-provider.js +406 -0
- package/dist/story-generator/llm-providers/index.d.ts +63 -0
- package/dist/story-generator/llm-providers/index.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/index.js +169 -0
- package/dist/story-generator/llm-providers/openai-provider.d.ts +24 -0
- package/dist/story-generator/llm-providers/openai-provider.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/openai-provider.js +458 -0
- package/dist/story-generator/llm-providers/settings-manager.d.ts +75 -0
- package/dist/story-generator/llm-providers/settings-manager.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/settings-manager.js +173 -0
- package/dist/story-generator/llm-providers/story-llm-service.d.ts +79 -0
- package/dist/story-generator/llm-providers/story-llm-service.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/story-llm-service.js +240 -0
- package/dist/story-generator/llm-providers/types.d.ts +153 -0
- package/dist/story-generator/llm-providers/types.d.ts.map +1 -0
- package/dist/story-generator/llm-providers/types.js +8 -0
- package/dist/story-generator/logger.d.ts +14 -0
- package/dist/story-generator/logger.d.ts.map +1 -0
- package/dist/story-generator/logger.js +96 -29
- package/dist/story-generator/postProcessStory.d.ts +6 -0
- package/dist/story-generator/postProcessStory.d.ts.map +1 -0
- package/dist/story-generator/productionGitignoreManager.d.ts +91 -0
- package/dist/story-generator/productionGitignoreManager.d.ts.map +1 -0
- package/dist/story-generator/promptGenerator.d.ts +48 -0
- package/dist/story-generator/promptGenerator.d.ts.map +1 -0
- package/dist/story-generator/promptGenerator.js +186 -1
- package/dist/story-generator/storyHistory.d.ts +44 -0
- package/dist/story-generator/storyHistory.d.ts.map +1 -0
- package/dist/story-generator/storySync.d.ts +68 -0
- package/dist/story-generator/storySync.d.ts.map +1 -0
- package/dist/story-generator/storyTracker.d.ts +48 -0
- package/dist/story-generator/storyTracker.d.ts.map +1 -0
- package/dist/story-generator/storyValidator.d.ts +6 -0
- package/dist/story-generator/storyValidator.d.ts.map +1 -0
- package/dist/story-generator/universalDesignSystemAdapter.d.ts +68 -0
- package/dist/story-generator/universalDesignSystemAdapter.d.ts.map +1 -0
- package/dist/story-generator/universalDesignSystemAdapter.js +138 -1
- package/dist/story-generator/urlRedirectService.d.ts +21 -0
- package/dist/story-generator/urlRedirectService.d.ts.map +1 -0
- package/dist/story-generator/validateStory.d.ts +19 -0
- package/dist/story-generator/validateStory.d.ts.map +1 -0
- package/dist/story-generator/validateStory.js +6 -2
- package/dist/story-generator/visionPrompts.d.ts +88 -0
- package/dist/story-generator/visionPrompts.d.ts.map +1 -0
- package/dist/story-generator/visionPrompts.js +462 -0
- package/dist/story-ui.config.d.ts +78 -0
- package/dist/story-ui.config.d.ts.map +1 -0
- package/dist/templates/StoryUI/StoryUIPanel.d.ts +4 -0
- package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -0
- package/dist/templates/StoryUI/StoryUIPanel.js +1874 -0
- package/dist/templates/StoryUI/StoryUIPanel.stories.d.ts +18 -0
- package/dist/templates/StoryUI/StoryUIPanel.stories.d.ts.map +1 -0
- package/dist/templates/StoryUI/StoryUIPanel.stories.js +37 -0
- package/dist/templates/StoryUI/index.d.ts +3 -0
- package/dist/templates/StoryUI/index.d.ts.map +1 -0
- package/dist/templates/StoryUI/index.js +2 -0
- package/package.json +17 -3
- package/templates/StoryUI/StoryUIPanel.tsx +1960 -384
- package/templates/StoryUI/index.tsx +1 -1
- package/templates/StoryUI/manager.tsx +264 -0
- package/templates/production-app/.env.example +11 -0
- package/templates/production-app/index.html +66 -0
- package/templates/production-app/package.json +30 -0
- package/templates/production-app/public/favicon.svg +5 -0
- package/templates/production-app/src/App.tsx +1560 -0
- package/templates/production-app/src/LivePreviewRenderer.tsx +420 -0
- package/templates/production-app/src/componentRegistry.ts +315 -0
- package/templates/production-app/src/considerations.ts +16 -0
- package/templates/production-app/src/index.css +284 -0
- package/templates/production-app/src/main.tsx +25 -0
- package/templates/production-app/tsconfig.json +32 -0
- package/templates/production-app/tsconfig.node.json +11 -0
- package/templates/production-app/vite.config.ts +83 -0
- package/templates/react-import-rule.json +2 -2
- package/dist/index.js +0 -12
- package/dist/story-ui.config.loader.js +0 -205
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini LLM Provider
|
|
3
|
+
*
|
|
4
|
+
* Implementation of the LLM provider interface for Google's Gemini models.
|
|
5
|
+
*/
|
|
6
|
+
import { BaseLLMProvider } from './base-provider.js';
|
|
7
|
+
import { logger } from '../logger.js';
|
|
8
|
+
// Gemini model definitions - Updated November 2025
|
|
9
|
+
// Reference: https://ai.google.dev/gemini-api/docs/gemini-3
|
|
10
|
+
const GEMINI_MODELS = [
|
|
11
|
+
// Gemini 3 Series - Latest (November 2025)
|
|
12
|
+
{
|
|
13
|
+
id: 'gemini-3-pro',
|
|
14
|
+
name: 'Gemini 3 Pro',
|
|
15
|
+
provider: 'gemini',
|
|
16
|
+
contextWindow: 1000000, // 1M tokens input
|
|
17
|
+
maxOutputTokens: 64000,
|
|
18
|
+
supportsVision: true,
|
|
19
|
+
supportsDocuments: true,
|
|
20
|
+
supportsFunctionCalling: true,
|
|
21
|
+
supportsStreaming: true,
|
|
22
|
+
supportsReasoning: true, // Native reasoning with thinking_level parameter
|
|
23
|
+
inputPricePer1kTokens: 0.002, // $2/million for <=200k context
|
|
24
|
+
outputPricePer1kTokens: 0.012, // $12/million output
|
|
25
|
+
description: 'Most intelligent Gemini model. PhD-level reasoning, 1501 Elo on LMArena.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: 'gemini-3-pro-preview',
|
|
29
|
+
name: 'Gemini 3 Pro (Preview)',
|
|
30
|
+
provider: 'gemini',
|
|
31
|
+
contextWindow: 1000000,
|
|
32
|
+
maxOutputTokens: 64000,
|
|
33
|
+
supportsVision: true,
|
|
34
|
+
supportsDocuments: true,
|
|
35
|
+
supportsFunctionCalling: true,
|
|
36
|
+
supportsStreaming: true,
|
|
37
|
+
supportsReasoning: true,
|
|
38
|
+
inputPricePer1kTokens: 0.002,
|
|
39
|
+
outputPricePer1kTokens: 0.012,
|
|
40
|
+
description: 'Preview version of Gemini 3 Pro with latest experimental features.',
|
|
41
|
+
},
|
|
42
|
+
// Gemini 2.0 Series
|
|
43
|
+
{
|
|
44
|
+
id: 'gemini-2.0-flash-exp',
|
|
45
|
+
name: 'Gemini 2.0 Flash Experimental',
|
|
46
|
+
provider: 'gemini',
|
|
47
|
+
contextWindow: 1048576,
|
|
48
|
+
maxOutputTokens: 8192,
|
|
49
|
+
supportsVision: true,
|
|
50
|
+
supportsDocuments: true,
|
|
51
|
+
supportsFunctionCalling: true,
|
|
52
|
+
supportsStreaming: true,
|
|
53
|
+
inputPricePer1kTokens: 0.00,
|
|
54
|
+
outputPricePer1kTokens: 0.00,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'gemini-2.0-flash',
|
|
58
|
+
name: 'Gemini 2.0 Flash',
|
|
59
|
+
provider: 'gemini',
|
|
60
|
+
contextWindow: 1048576,
|
|
61
|
+
maxOutputTokens: 8192,
|
|
62
|
+
supportsVision: true,
|
|
63
|
+
supportsDocuments: true,
|
|
64
|
+
supportsFunctionCalling: true,
|
|
65
|
+
supportsStreaming: true,
|
|
66
|
+
inputPricePer1kTokens: 0.00,
|
|
67
|
+
outputPricePer1kTokens: 0.00,
|
|
68
|
+
},
|
|
69
|
+
// Gemini 1.5 Series (Legacy)
|
|
70
|
+
{
|
|
71
|
+
id: 'gemini-1.5-pro',
|
|
72
|
+
name: 'Gemini 1.5 Pro',
|
|
73
|
+
provider: 'gemini',
|
|
74
|
+
contextWindow: 2097152,
|
|
75
|
+
maxOutputTokens: 8192,
|
|
76
|
+
supportsVision: true,
|
|
77
|
+
supportsDocuments: true,
|
|
78
|
+
supportsFunctionCalling: true,
|
|
79
|
+
supportsStreaming: true,
|
|
80
|
+
inputPricePer1kTokens: 0.00125,
|
|
81
|
+
outputPricePer1kTokens: 0.005,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: 'gemini-1.5-flash',
|
|
85
|
+
name: 'Gemini 1.5 Flash',
|
|
86
|
+
provider: 'gemini',
|
|
87
|
+
contextWindow: 1048576,
|
|
88
|
+
maxOutputTokens: 8192,
|
|
89
|
+
supportsVision: true,
|
|
90
|
+
supportsDocuments: true,
|
|
91
|
+
supportsFunctionCalling: true,
|
|
92
|
+
supportsStreaming: true,
|
|
93
|
+
inputPricePer1kTokens: 0.000075,
|
|
94
|
+
outputPricePer1kTokens: 0.0003,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: 'gemini-1.5-flash-8b',
|
|
98
|
+
name: 'Gemini 1.5 Flash 8B',
|
|
99
|
+
provider: 'gemini',
|
|
100
|
+
contextWindow: 1048576,
|
|
101
|
+
maxOutputTokens: 8192,
|
|
102
|
+
supportsVision: true,
|
|
103
|
+
supportsDocuments: true,
|
|
104
|
+
supportsFunctionCalling: true,
|
|
105
|
+
supportsStreaming: true,
|
|
106
|
+
inputPricePer1kTokens: 0.0000375,
|
|
107
|
+
outputPricePer1kTokens: 0.00015,
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
// Default model
|
|
111
|
+
const DEFAULT_MODEL = 'gemini-2.0-flash';
|
|
112
|
+
// API configuration
|
|
113
|
+
const GEMINI_API_BASE = 'https://generativelanguage.googleapis.com/v1beta/models';
|
|
114
|
+
export class GeminiProvider extends BaseLLMProvider {
|
|
115
|
+
constructor(config) {
|
|
116
|
+
super(config);
|
|
117
|
+
this.name = 'Gemini';
|
|
118
|
+
this.type = 'gemini';
|
|
119
|
+
this.supportedModels = GEMINI_MODELS;
|
|
120
|
+
// Set the provider type after base constructor
|
|
121
|
+
this.setProviderType();
|
|
122
|
+
// Set default model if not provided
|
|
123
|
+
if (!this.config.model) {
|
|
124
|
+
this.config.model = DEFAULT_MODEL;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
getApiUrl(model, stream = false) {
|
|
128
|
+
const method = stream ? 'streamGenerateContent' : 'generateContent';
|
|
129
|
+
return `${GEMINI_API_BASE}/${model}:${method}`;
|
|
130
|
+
}
|
|
131
|
+
async chat(messages, options) {
|
|
132
|
+
this.validateMessages(messages);
|
|
133
|
+
this.logRequest(messages, options);
|
|
134
|
+
const apiKey = this.config.apiKey;
|
|
135
|
+
if (!apiKey) {
|
|
136
|
+
throw new Error('Gemini API key not configured');
|
|
137
|
+
}
|
|
138
|
+
const model = options?.model || this.config.model;
|
|
139
|
+
const geminiContents = this.convertMessages(messages);
|
|
140
|
+
const systemPrompt = this.buildSystemPrompt(options);
|
|
141
|
+
const requestBody = {
|
|
142
|
+
contents: geminiContents,
|
|
143
|
+
generationConfig: {
|
|
144
|
+
maxOutputTokens: options?.maxTokens || this.getSelectedModel()?.maxOutputTokens || 8192,
|
|
145
|
+
...(options?.temperature !== undefined && { temperature: options.temperature }),
|
|
146
|
+
...(options?.topP !== undefined && { topP: options.topP }),
|
|
147
|
+
...(options?.topK !== undefined && { topK: options.topK }),
|
|
148
|
+
...(options?.stopSequences?.length && { stopSequences: options.stopSequences }),
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
// Add system instruction if provided
|
|
152
|
+
if (systemPrompt) {
|
|
153
|
+
requestBody.systemInstruction = {
|
|
154
|
+
parts: [{ text: systemPrompt }],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const url = `${this.getApiUrl(model)}?key=${apiKey}`;
|
|
158
|
+
try {
|
|
159
|
+
const response = await fetch(url, {
|
|
160
|
+
method: 'POST',
|
|
161
|
+
headers: {
|
|
162
|
+
'Content-Type': 'application/json',
|
|
163
|
+
},
|
|
164
|
+
body: JSON.stringify(requestBody),
|
|
165
|
+
signal: AbortSignal.timeout(this.config.timeout || 120000),
|
|
166
|
+
});
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
const errorBody = await response.text();
|
|
169
|
+
logger.error('Gemini API error response', { status: response.status, body: errorBody });
|
|
170
|
+
throw new Error(`Gemini API error: ${response.status} - ${errorBody}`);
|
|
171
|
+
}
|
|
172
|
+
const data = (await response.json());
|
|
173
|
+
const chatResponse = this.convertResponse(data, model);
|
|
174
|
+
this.logResponse(chatResponse);
|
|
175
|
+
return chatResponse;
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (error instanceof Error && error.name === 'TimeoutError') {
|
|
179
|
+
throw new Error(`Gemini API request timed out after ${this.config.timeout}ms`);
|
|
180
|
+
}
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async *chatStream(messages, options) {
|
|
185
|
+
this.validateMessages(messages);
|
|
186
|
+
this.logRequest(messages, options);
|
|
187
|
+
const apiKey = this.config.apiKey;
|
|
188
|
+
if (!apiKey) {
|
|
189
|
+
yield { type: 'error', error: 'Gemini API key not configured' };
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const model = options?.model || this.config.model;
|
|
193
|
+
const geminiContents = this.convertMessages(messages);
|
|
194
|
+
const systemPrompt = this.buildSystemPrompt(options);
|
|
195
|
+
const requestBody = {
|
|
196
|
+
contents: geminiContents,
|
|
197
|
+
generationConfig: {
|
|
198
|
+
maxOutputTokens: options?.maxTokens || this.getSelectedModel()?.maxOutputTokens || 8192,
|
|
199
|
+
...(options?.temperature !== undefined && { temperature: options.temperature }),
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
if (systemPrompt) {
|
|
203
|
+
requestBody.systemInstruction = {
|
|
204
|
+
parts: [{ text: systemPrompt }],
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const url = `${this.getApiUrl(model, true)}?key=${apiKey}&alt=sse`;
|
|
208
|
+
try {
|
|
209
|
+
const response = await fetch(url, {
|
|
210
|
+
method: 'POST',
|
|
211
|
+
headers: {
|
|
212
|
+
'Content-Type': 'application/json',
|
|
213
|
+
},
|
|
214
|
+
body: JSON.stringify(requestBody),
|
|
215
|
+
signal: AbortSignal.timeout(this.config.timeout || 120000),
|
|
216
|
+
});
|
|
217
|
+
if (!response.ok) {
|
|
218
|
+
const errorBody = await response.text();
|
|
219
|
+
yield { type: 'error', error: `Gemini API error: ${response.status} - ${errorBody}` };
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const reader = response.body?.getReader();
|
|
223
|
+
if (!reader) {
|
|
224
|
+
yield { type: 'error', error: 'No response body' };
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const decoder = new TextDecoder();
|
|
228
|
+
let buffer = '';
|
|
229
|
+
let promptTokens = 0;
|
|
230
|
+
let completionTokens = 0;
|
|
231
|
+
while (true) {
|
|
232
|
+
const { done, value } = await reader.read();
|
|
233
|
+
if (done)
|
|
234
|
+
break;
|
|
235
|
+
buffer += decoder.decode(value, { stream: true });
|
|
236
|
+
const lines = buffer.split('\n');
|
|
237
|
+
buffer = lines.pop() || '';
|
|
238
|
+
for (const line of lines) {
|
|
239
|
+
if (line.startsWith('data: ')) {
|
|
240
|
+
const data = line.slice(6);
|
|
241
|
+
if (!data || data === '[DONE]')
|
|
242
|
+
continue;
|
|
243
|
+
try {
|
|
244
|
+
const event = JSON.parse(data);
|
|
245
|
+
// Extract text from candidates
|
|
246
|
+
const text = event.candidates?.[0]?.content?.parts
|
|
247
|
+
?.map(p => p.text)
|
|
248
|
+
.filter(Boolean)
|
|
249
|
+
.join('');
|
|
250
|
+
if (text) {
|
|
251
|
+
yield { type: 'text', content: text };
|
|
252
|
+
}
|
|
253
|
+
// Extract usage metadata
|
|
254
|
+
if (event.usageMetadata) {
|
|
255
|
+
promptTokens = event.usageMetadata.promptTokenCount || 0;
|
|
256
|
+
completionTokens = event.usageMetadata.candidatesTokenCount || 0;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
// Skip malformed JSON
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
yield {
|
|
266
|
+
type: 'done',
|
|
267
|
+
usage: {
|
|
268
|
+
promptTokens,
|
|
269
|
+
completionTokens,
|
|
270
|
+
totalTokens: promptTokens + completionTokens,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
yield {
|
|
276
|
+
type: 'error',
|
|
277
|
+
error: error instanceof Error ? error.message : String(error),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async validateApiKey(apiKey) {
|
|
282
|
+
try {
|
|
283
|
+
// Make a minimal API call to validate the key
|
|
284
|
+
const url = `${this.getApiUrl('gemini-1.5-flash')}?key=${apiKey}`;
|
|
285
|
+
const response = await fetch(url, {
|
|
286
|
+
method: 'POST',
|
|
287
|
+
headers: {
|
|
288
|
+
'Content-Type': 'application/json',
|
|
289
|
+
},
|
|
290
|
+
body: JSON.stringify({
|
|
291
|
+
contents: [{ parts: [{ text: 'Hi' }] }],
|
|
292
|
+
generationConfig: { maxOutputTokens: 1 },
|
|
293
|
+
}),
|
|
294
|
+
signal: AbortSignal.timeout(10000),
|
|
295
|
+
});
|
|
296
|
+
if (response.ok) {
|
|
297
|
+
return {
|
|
298
|
+
valid: true,
|
|
299
|
+
models: this.supportedModels,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const errorBody = await response.text();
|
|
303
|
+
// Check for specific error types
|
|
304
|
+
if (response.status === 400 && errorBody.includes('API_KEY_INVALID')) {
|
|
305
|
+
return {
|
|
306
|
+
valid: false,
|
|
307
|
+
error: 'Invalid API key',
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
valid: false,
|
|
312
|
+
error: `API validation failed: ${errorBody}`,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
return {
|
|
317
|
+
valid: false,
|
|
318
|
+
error: error instanceof Error ? error.message : 'Validation failed',
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Convert our message format to Gemini format
|
|
323
|
+
convertMessages(messages) {
|
|
324
|
+
return messages
|
|
325
|
+
.filter(msg => msg.role !== 'system') // System messages handled separately
|
|
326
|
+
.map(msg => ({
|
|
327
|
+
role: msg.role === 'assistant' ? 'model' : 'user',
|
|
328
|
+
parts: this.convertContent(msg.content),
|
|
329
|
+
}));
|
|
330
|
+
}
|
|
331
|
+
convertContent(content) {
|
|
332
|
+
if (typeof content === 'string') {
|
|
333
|
+
return [{ text: content }];
|
|
334
|
+
}
|
|
335
|
+
return content.map(item => {
|
|
336
|
+
if (item.type === 'text') {
|
|
337
|
+
return { text: item.text };
|
|
338
|
+
}
|
|
339
|
+
if (item.type === 'image') {
|
|
340
|
+
const imageContent = item;
|
|
341
|
+
if (imageContent.source.type === 'base64' && imageContent.source.data) {
|
|
342
|
+
return {
|
|
343
|
+
inlineData: {
|
|
344
|
+
mimeType: imageContent.source.mediaType || 'image/png',
|
|
345
|
+
data: imageContent.source.data,
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
// URL images - Gemini requires base64, so we store for async processing
|
|
350
|
+
// NOTE: For Gemini, URL images should be pre-converted to base64 using imageProcessor.ts
|
|
351
|
+
// If a URL image reaches here, it means it wasn't pre-processed
|
|
352
|
+
if (imageContent.source.url) {
|
|
353
|
+
logger.warn(`Gemini provider received URL image that wasn't pre-converted to base64. URL: ${imageContent.source.url}`);
|
|
354
|
+
logger.warn('For best results, use imageProcessor.processImageInputs() to convert URL images before sending to Gemini.');
|
|
355
|
+
return { text: `[Image URL - requires base64 conversion: ${imageContent.source.url}]` };
|
|
356
|
+
}
|
|
357
|
+
return { text: '[Invalid image content]' };
|
|
358
|
+
}
|
|
359
|
+
// Document type
|
|
360
|
+
if (item.type === 'document') {
|
|
361
|
+
return { text: `[Document: ${item.source.name || 'unnamed'}]` };
|
|
362
|
+
}
|
|
363
|
+
return { text: '' };
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
convertResponse(data, model) {
|
|
367
|
+
const candidate = data.candidates?.[0];
|
|
368
|
+
const textParts = candidate?.content?.parts || [];
|
|
369
|
+
const content = textParts.map(p => p.text || '').join('');
|
|
370
|
+
return {
|
|
371
|
+
id: `gemini-${Date.now()}`, // Gemini doesn't return an ID
|
|
372
|
+
model,
|
|
373
|
+
content,
|
|
374
|
+
finishReason: this.mapFinishReason(candidate?.finishReason),
|
|
375
|
+
usage: {
|
|
376
|
+
promptTokens: data.usageMetadata?.promptTokenCount || 0,
|
|
377
|
+
completionTokens: data.usageMetadata?.candidatesTokenCount || 0,
|
|
378
|
+
totalTokens: data.usageMetadata?.totalTokenCount || 0,
|
|
379
|
+
},
|
|
380
|
+
raw: data,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
mapFinishReason(finishReason) {
|
|
384
|
+
switch (finishReason) {
|
|
385
|
+
case 'STOP':
|
|
386
|
+
return 'stop';
|
|
387
|
+
case 'MAX_TOKENS':
|
|
388
|
+
return 'length';
|
|
389
|
+
case 'SAFETY':
|
|
390
|
+
case 'RECITATION':
|
|
391
|
+
return 'content_filter';
|
|
392
|
+
default:
|
|
393
|
+
return 'stop';
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// Token estimation for Gemini
|
|
397
|
+
estimateTokens(text) {
|
|
398
|
+
// Gemini uses a similar tokenization to other LLMs
|
|
399
|
+
// Rough estimate: ~4 characters per token
|
|
400
|
+
return Math.ceil(text.length / 4);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// Factory function
|
|
404
|
+
export function createGeminiProvider(config) {
|
|
405
|
+
return new GeminiProvider(config);
|
|
406
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Providers Module
|
|
3
|
+
*
|
|
4
|
+
* Exports all LLM providers and the provider registry for managing them.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export { BaseLLMProvider } from './base-provider.js';
|
|
8
|
+
export { ClaudeProvider, createClaudeProvider } from './claude-provider.js';
|
|
9
|
+
export { OpenAIProvider, createOpenAIProvider } from './openai-provider.js';
|
|
10
|
+
export { GeminiProvider, createGeminiProvider } from './gemini-provider.js';
|
|
11
|
+
import { LLMProvider, ProviderType, ProviderRegistry, ModelInfo, ProviderConfig } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Default Provider Registry Implementation
|
|
14
|
+
*/
|
|
15
|
+
declare class DefaultProviderRegistry implements ProviderRegistry {
|
|
16
|
+
private providers;
|
|
17
|
+
private defaultProviderType;
|
|
18
|
+
constructor();
|
|
19
|
+
private registerBuiltInProviders;
|
|
20
|
+
register(provider: LLMProvider): void;
|
|
21
|
+
get(type: ProviderType): LLMProvider | undefined;
|
|
22
|
+
getAll(): LLMProvider[];
|
|
23
|
+
getAvailableModels(): ModelInfo[];
|
|
24
|
+
getDefault(): LLMProvider | undefined;
|
|
25
|
+
setDefault(type: ProviderType): void;
|
|
26
|
+
/**
|
|
27
|
+
* Configure a provider with API key and settings
|
|
28
|
+
*/
|
|
29
|
+
configureProvider(type: ProviderType, config: Partial<ProviderConfig>): void;
|
|
30
|
+
/**
|
|
31
|
+
* Get a provider that supports a specific model
|
|
32
|
+
*/
|
|
33
|
+
getProviderForModel(modelId: string): LLMProvider | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Check if any provider is configured and ready to use
|
|
36
|
+
*/
|
|
37
|
+
hasConfiguredProvider(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Get all configured providers
|
|
40
|
+
*/
|
|
41
|
+
getConfiguredProviders(): LLMProvider[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the global provider registry instance
|
|
45
|
+
*/
|
|
46
|
+
export declare function getProviderRegistry(): DefaultProviderRegistry;
|
|
47
|
+
/**
|
|
48
|
+
* Convenience function to get a provider by type
|
|
49
|
+
*/
|
|
50
|
+
export declare function getProvider(type: ProviderType): LLMProvider | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Convenience function to get the default provider
|
|
53
|
+
*/
|
|
54
|
+
export declare function getDefaultProvider(): LLMProvider | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Convenience function to configure a provider
|
|
57
|
+
*/
|
|
58
|
+
export declare function configureProvider(type: ProviderType, config: Partial<ProviderConfig>): void;
|
|
59
|
+
/**
|
|
60
|
+
* Initialize providers from environment variables
|
|
61
|
+
*/
|
|
62
|
+
export declare function initializeFromEnv(): void;
|
|
63
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../story-generator/llm-providers/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG5E,OAAO,EACL,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,cAAc,EACf,MAAM,YAAY,CAAC;AAMpB;;GAEG;AACH,cAAM,uBAAwB,YAAW,gBAAgB;IACvD,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,mBAAmB,CAA6B;;IAOxD,OAAO,CAAC,wBAAwB;IAQhC,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAUrC,GAAG,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS;IAIhD,MAAM,IAAI,WAAW,EAAE;IAIvB,kBAAkB,IAAI,SAAS,EAAE;IAQjC,UAAU,IAAI,WAAW,GAAG,SAAS;IAKrC,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAQpC;;OAEG;IACH,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAQ5E;;OAEG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAS7D;;OAEG;IACH,qBAAqB,IAAI,OAAO;IAShC;;OAEG;IACH,sBAAsB,IAAI,WAAW,EAAE;CAGxC;AAKD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,uBAAuB,CAK7D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS,CAEvE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,GAAG,SAAS,CAE5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAC9B,IAAI,CAEN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAiCxC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Providers Module
|
|
3
|
+
*
|
|
4
|
+
* Exports all LLM providers and the provider registry for managing them.
|
|
5
|
+
*/
|
|
6
|
+
// Types
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
// Base provider
|
|
9
|
+
export { BaseLLMProvider } from './base-provider.js';
|
|
10
|
+
// Provider implementations
|
|
11
|
+
export { ClaudeProvider, createClaudeProvider } from './claude-provider.js';
|
|
12
|
+
export { OpenAIProvider, createOpenAIProvider } from './openai-provider.js';
|
|
13
|
+
export { GeminiProvider, createGeminiProvider } from './gemini-provider.js';
|
|
14
|
+
import { ClaudeProvider } from './claude-provider.js';
|
|
15
|
+
import { OpenAIProvider } from './openai-provider.js';
|
|
16
|
+
import { GeminiProvider } from './gemini-provider.js';
|
|
17
|
+
import { logger } from '../logger.js';
|
|
18
|
+
/**
|
|
19
|
+
* Default Provider Registry Implementation
|
|
20
|
+
*/
|
|
21
|
+
class DefaultProviderRegistry {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.providers = new Map();
|
|
24
|
+
this.defaultProviderType = null;
|
|
25
|
+
// Register built-in providers
|
|
26
|
+
this.registerBuiltInProviders();
|
|
27
|
+
}
|
|
28
|
+
registerBuiltInProviders() {
|
|
29
|
+
// Register all built-in providers
|
|
30
|
+
this.register(new ClaudeProvider());
|
|
31
|
+
this.register(new OpenAIProvider());
|
|
32
|
+
this.register(new GeminiProvider());
|
|
33
|
+
logger.debug('Registered built-in providers: Claude, OpenAI, Gemini');
|
|
34
|
+
}
|
|
35
|
+
register(provider) {
|
|
36
|
+
this.providers.set(provider.type, provider);
|
|
37
|
+
logger.debug(`Registered provider: ${provider.name} (${provider.type})`);
|
|
38
|
+
// Set as default if it's the first provider
|
|
39
|
+
if (!this.defaultProviderType) {
|
|
40
|
+
this.defaultProviderType = provider.type;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
get(type) {
|
|
44
|
+
return this.providers.get(type);
|
|
45
|
+
}
|
|
46
|
+
getAll() {
|
|
47
|
+
return Array.from(this.providers.values());
|
|
48
|
+
}
|
|
49
|
+
getAvailableModels() {
|
|
50
|
+
const models = [];
|
|
51
|
+
for (const provider of this.providers.values()) {
|
|
52
|
+
models.push(...provider.supportedModels);
|
|
53
|
+
}
|
|
54
|
+
return models;
|
|
55
|
+
}
|
|
56
|
+
getDefault() {
|
|
57
|
+
if (!this.defaultProviderType)
|
|
58
|
+
return undefined;
|
|
59
|
+
return this.providers.get(this.defaultProviderType);
|
|
60
|
+
}
|
|
61
|
+
setDefault(type) {
|
|
62
|
+
if (!this.providers.has(type)) {
|
|
63
|
+
throw new Error(`Provider type '${type}' is not registered`);
|
|
64
|
+
}
|
|
65
|
+
this.defaultProviderType = type;
|
|
66
|
+
logger.debug(`Set default provider to: ${type}`);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Configure a provider with API key and settings
|
|
70
|
+
*/
|
|
71
|
+
configureProvider(type, config) {
|
|
72
|
+
const provider = this.providers.get(type);
|
|
73
|
+
if (!provider) {
|
|
74
|
+
throw new Error(`Provider type '${type}' is not registered`);
|
|
75
|
+
}
|
|
76
|
+
provider.configure({ ...config, provider: type });
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get a provider that supports a specific model
|
|
80
|
+
*/
|
|
81
|
+
getProviderForModel(modelId) {
|
|
82
|
+
for (const provider of this.providers.values()) {
|
|
83
|
+
if (provider.supportedModels.some(m => m.id === modelId)) {
|
|
84
|
+
return provider;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if any provider is configured and ready to use
|
|
91
|
+
*/
|
|
92
|
+
hasConfiguredProvider() {
|
|
93
|
+
for (const provider of this.providers.values()) {
|
|
94
|
+
if (provider.isConfigured()) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get all configured providers
|
|
102
|
+
*/
|
|
103
|
+
getConfiguredProviders() {
|
|
104
|
+
return this.getAll().filter(p => p.isConfigured());
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Singleton registry instance
|
|
108
|
+
let registryInstance = null;
|
|
109
|
+
/**
|
|
110
|
+
* Get the global provider registry instance
|
|
111
|
+
*/
|
|
112
|
+
export function getProviderRegistry() {
|
|
113
|
+
if (!registryInstance) {
|
|
114
|
+
registryInstance = new DefaultProviderRegistry();
|
|
115
|
+
}
|
|
116
|
+
return registryInstance;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Convenience function to get a provider by type
|
|
120
|
+
*/
|
|
121
|
+
export function getProvider(type) {
|
|
122
|
+
return getProviderRegistry().get(type);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Convenience function to get the default provider
|
|
126
|
+
*/
|
|
127
|
+
export function getDefaultProvider() {
|
|
128
|
+
return getProviderRegistry().getDefault();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Convenience function to configure a provider
|
|
132
|
+
*/
|
|
133
|
+
export function configureProvider(type, config) {
|
|
134
|
+
getProviderRegistry().configureProvider(type, config);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Initialize providers from environment variables
|
|
138
|
+
*/
|
|
139
|
+
export function initializeFromEnv() {
|
|
140
|
+
const registry = getProviderRegistry();
|
|
141
|
+
// Configure Claude if API key is present
|
|
142
|
+
const claudeKey = process.env.CLAUDE_API_KEY || process.env.ANTHROPIC_API_KEY;
|
|
143
|
+
if (claudeKey) {
|
|
144
|
+
registry.configureProvider('claude', {
|
|
145
|
+
apiKey: claudeKey,
|
|
146
|
+
model: process.env.CLAUDE_MODEL || 'claude-sonnet-4-5-20250929',
|
|
147
|
+
});
|
|
148
|
+
logger.info('Claude provider configured from environment');
|
|
149
|
+
}
|
|
150
|
+
// Configure OpenAI if API key is present
|
|
151
|
+
const openaiKey = process.env.OPENAI_API_KEY;
|
|
152
|
+
if (openaiKey) {
|
|
153
|
+
registry.configureProvider('openai', {
|
|
154
|
+
apiKey: openaiKey,
|
|
155
|
+
model: process.env.OPENAI_MODEL || 'gpt-4o',
|
|
156
|
+
organizationId: process.env.OPENAI_ORG_ID,
|
|
157
|
+
});
|
|
158
|
+
logger.info('OpenAI provider configured from environment');
|
|
159
|
+
}
|
|
160
|
+
// Configure Gemini if API key is present
|
|
161
|
+
const geminiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
|
|
162
|
+
if (geminiKey) {
|
|
163
|
+
registry.configureProvider('gemini', {
|
|
164
|
+
apiKey: geminiKey,
|
|
165
|
+
model: process.env.GEMINI_MODEL || 'gemini-2.0-flash',
|
|
166
|
+
});
|
|
167
|
+
logger.info('Gemini provider configured from environment');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI LLM Provider
|
|
3
|
+
*
|
|
4
|
+
* Implementation of the LLM provider interface for OpenAI's GPT models.
|
|
5
|
+
*/
|
|
6
|
+
import { ProviderType, ProviderConfig, ModelInfo, ChatMessage, ChatOptions, ChatResponse, StreamChunk, ValidationResult } from './types.js';
|
|
7
|
+
import { BaseLLMProvider } from './base-provider.js';
|
|
8
|
+
export declare class OpenAIProvider extends BaseLLMProvider {
|
|
9
|
+
readonly name = "OpenAI";
|
|
10
|
+
readonly type: ProviderType;
|
|
11
|
+
readonly supportedModels: ModelInfo[];
|
|
12
|
+
constructor(config?: Partial<ProviderConfig>);
|
|
13
|
+
chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse>;
|
|
14
|
+
chatStream(messages: ChatMessage[], options?: ChatOptions): AsyncIterable<StreamChunk>;
|
|
15
|
+
validateApiKey(apiKey: string): Promise<ValidationResult>;
|
|
16
|
+
private convertMessages;
|
|
17
|
+
private extractTextContent;
|
|
18
|
+
private convertContent;
|
|
19
|
+
private convertResponse;
|
|
20
|
+
private mapFinishReason;
|
|
21
|
+
estimateTokens(text: string): number;
|
|
22
|
+
}
|
|
23
|
+
export declare function createOpenAIProvider(config?: Partial<ProviderConfig>): OpenAIProvider;
|
|
24
|
+
//# sourceMappingURL=openai-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-provider.d.ts","sourceRoot":"","sources":["../../../story-generator/llm-providers/openai-provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,YAAY,EACZ,cAAc,EACd,SAAS,EACT,WAAW,EACX,WAAW,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAGjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AA+LrD,qBAAa,cAAe,SAAQ,eAAe;IACjD,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAY;IACvC,QAAQ,CAAC,eAAe,cAAiB;gBAE7B,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAUtC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IA2D1E,UAAU,CACf,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,CAAC,EAAE,WAAW,GACpB,aAAa,CAAC,WAAW,CAAC;IAqGvB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA+C/D,OAAO,CAAC,eAAe;IA8BvB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,cAAc;IAiCtB,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,eAAe;IAmBvB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAKrC;AAGD,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAErF"}
|