@tpitre/story-ui 2.2.0 → 2.3.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.
Files changed (188) hide show
  1. package/.env.sample +82 -11
  2. package/README.md +89 -0
  3. package/dist/cli/deploy.d.ts +17 -0
  4. package/dist/cli/deploy.d.ts.map +1 -0
  5. package/dist/cli/deploy.js +696 -0
  6. package/dist/cli/index.d.ts +3 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +26 -2
  9. package/dist/cli/setup.d.ts +11 -0
  10. package/dist/cli/setup.d.ts.map +1 -0
  11. package/dist/cli/setup.js +437 -110
  12. package/dist/mcp-server/index.d.ts +2 -0
  13. package/dist/mcp-server/index.d.ts.map +1 -0
  14. package/dist/mcp-server/index.js +120 -2
  15. package/dist/mcp-server/mcp-stdio-server.d.ts +3 -0
  16. package/dist/mcp-server/mcp-stdio-server.d.ts.map +1 -0
  17. package/dist/mcp-server/mcp-stdio-server.js +8 -1
  18. package/dist/mcp-server/routes/claude.d.ts +3 -0
  19. package/dist/mcp-server/routes/claude.d.ts.map +1 -0
  20. package/dist/mcp-server/routes/claude.js +60 -23
  21. package/dist/mcp-server/routes/components.d.ts +4 -0
  22. package/dist/mcp-server/routes/components.d.ts.map +1 -0
  23. package/dist/mcp-server/routes/frameworks.d.ts +38 -0
  24. package/dist/mcp-server/routes/frameworks.d.ts.map +1 -0
  25. package/dist/mcp-server/routes/frameworks.js +183 -0
  26. package/dist/mcp-server/routes/generateStory.d.ts +3 -0
  27. package/dist/mcp-server/routes/generateStory.d.ts.map +1 -0
  28. package/dist/mcp-server/routes/generateStory.js +160 -76
  29. package/dist/mcp-server/routes/generateStoryStream.d.ts +12 -0
  30. package/dist/mcp-server/routes/generateStoryStream.d.ts.map +1 -0
  31. package/dist/mcp-server/routes/generateStoryStream.js +947 -0
  32. package/dist/mcp-server/routes/hybridStories.d.ts +18 -0
  33. package/dist/mcp-server/routes/hybridStories.d.ts.map +1 -0
  34. package/dist/mcp-server/routes/mcpRemote.d.ts +14 -0
  35. package/dist/mcp-server/routes/mcpRemote.d.ts.map +1 -0
  36. package/dist/mcp-server/routes/mcpRemote.js +489 -0
  37. package/dist/mcp-server/routes/memoryStories.d.ts +26 -0
  38. package/dist/mcp-server/routes/memoryStories.d.ts.map +1 -0
  39. package/dist/mcp-server/routes/providers.d.ts +89 -0
  40. package/dist/mcp-server/routes/providers.d.ts.map +1 -0
  41. package/dist/mcp-server/routes/providers.js +369 -0
  42. package/dist/mcp-server/routes/storySync.d.ts +26 -0
  43. package/dist/mcp-server/routes/storySync.d.ts.map +1 -0
  44. package/dist/mcp-server/routes/streamTypes.d.ts +110 -0
  45. package/dist/mcp-server/routes/streamTypes.d.ts.map +1 -0
  46. package/dist/mcp-server/routes/streamTypes.js +18 -0
  47. package/dist/mcp-server/sessionManager.d.ts +50 -0
  48. package/dist/mcp-server/sessionManager.d.ts.map +1 -0
  49. package/dist/story-generator/componentBlacklist.d.ts +21 -0
  50. package/dist/story-generator/componentBlacklist.d.ts.map +1 -0
  51. package/dist/story-generator/componentDiscovery.d.ts +28 -0
  52. package/dist/story-generator/componentDiscovery.d.ts.map +1 -0
  53. package/dist/story-generator/componentRegistryGenerator.d.ts +49 -0
  54. package/dist/story-generator/componentRegistryGenerator.d.ts.map +1 -0
  55. package/dist/story-generator/componentRegistryGenerator.js +205 -0
  56. package/dist/story-generator/configLoader.d.ts +33 -0
  57. package/dist/story-generator/configLoader.d.ts.map +1 -0
  58. package/dist/story-generator/considerationsLoader.d.ts +32 -0
  59. package/dist/story-generator/considerationsLoader.d.ts.map +1 -0
  60. package/dist/story-generator/documentation-sources.d.ts +28 -0
  61. package/dist/story-generator/documentation-sources.d.ts.map +1 -0
  62. package/dist/story-generator/documentationLoader.d.ts +64 -0
  63. package/dist/story-generator/documentationLoader.d.ts.map +1 -0
  64. package/dist/story-generator/dynamicPackageDiscovery.d.ts +97 -0
  65. package/dist/story-generator/dynamicPackageDiscovery.d.ts.map +1 -0
  66. package/dist/story-generator/enhancedComponentDiscovery.d.ts +125 -0
  67. package/dist/story-generator/enhancedComponentDiscovery.d.ts.map +1 -0
  68. package/dist/story-generator/enhancedComponentDiscovery.js +111 -11
  69. package/dist/story-generator/framework-adapters/angular-adapter.d.ts +40 -0
  70. package/dist/story-generator/framework-adapters/angular-adapter.d.ts.map +1 -0
  71. package/dist/story-generator/framework-adapters/angular-adapter.js +427 -0
  72. package/dist/story-generator/framework-adapters/base-adapter.d.ts +75 -0
  73. package/dist/story-generator/framework-adapters/base-adapter.d.ts.map +1 -0
  74. package/dist/story-generator/framework-adapters/base-adapter.js +147 -0
  75. package/dist/story-generator/framework-adapters/framework-detector.d.ts +55 -0
  76. package/dist/story-generator/framework-adapters/framework-detector.d.ts.map +1 -0
  77. package/dist/story-generator/framework-adapters/framework-detector.js +323 -0
  78. package/dist/story-generator/framework-adapters/index.d.ts +97 -0
  79. package/dist/story-generator/framework-adapters/index.d.ts.map +1 -0
  80. package/dist/story-generator/framework-adapters/index.js +198 -0
  81. package/dist/story-generator/framework-adapters/react-adapter.d.ts +40 -0
  82. package/dist/story-generator/framework-adapters/react-adapter.d.ts.map +1 -0
  83. package/dist/story-generator/framework-adapters/react-adapter.js +316 -0
  84. package/dist/story-generator/framework-adapters/svelte-adapter.d.ts +40 -0
  85. package/dist/story-generator/framework-adapters/svelte-adapter.d.ts.map +1 -0
  86. package/dist/story-generator/framework-adapters/svelte-adapter.js +372 -0
  87. package/dist/story-generator/framework-adapters/types.d.ts +182 -0
  88. package/dist/story-generator/framework-adapters/types.d.ts.map +1 -0
  89. package/dist/story-generator/framework-adapters/types.js +8 -0
  90. package/dist/story-generator/framework-adapters/vue-adapter.d.ts +36 -0
  91. package/dist/story-generator/framework-adapters/vue-adapter.d.ts.map +1 -0
  92. package/dist/story-generator/framework-adapters/vue-adapter.js +336 -0
  93. package/dist/story-generator/framework-adapters/web-components-adapter.d.ts +54 -0
  94. package/dist/story-generator/framework-adapters/web-components-adapter.d.ts.map +1 -0
  95. package/dist/story-generator/framework-adapters/web-components-adapter.js +387 -0
  96. package/dist/story-generator/generateStory.d.ts +7 -0
  97. package/dist/story-generator/generateStory.d.ts.map +1 -0
  98. package/dist/story-generator/gitignoreManager.d.ts +50 -0
  99. package/dist/story-generator/gitignoreManager.d.ts.map +1 -0
  100. package/dist/story-generator/imageProcessor.d.ts +80 -0
  101. package/dist/story-generator/imageProcessor.d.ts.map +1 -0
  102. package/dist/story-generator/imageProcessor.js +391 -0
  103. package/dist/story-generator/inMemoryStoryService.d.ts +89 -0
  104. package/dist/story-generator/inMemoryStoryService.d.ts.map +1 -0
  105. package/dist/story-generator/llm-providers/base-provider.d.ts +36 -0
  106. package/dist/story-generator/llm-providers/base-provider.d.ts.map +1 -0
  107. package/dist/story-generator/llm-providers/base-provider.js +135 -0
  108. package/dist/story-generator/llm-providers/claude-provider.d.ts +23 -0
  109. package/dist/story-generator/llm-providers/claude-provider.d.ts.map +1 -0
  110. package/dist/story-generator/llm-providers/claude-provider.js +414 -0
  111. package/dist/story-generator/llm-providers/gemini-provider.d.ts +24 -0
  112. package/dist/story-generator/llm-providers/gemini-provider.d.ts.map +1 -0
  113. package/dist/story-generator/llm-providers/gemini-provider.js +406 -0
  114. package/dist/story-generator/llm-providers/index.d.ts +63 -0
  115. package/dist/story-generator/llm-providers/index.d.ts.map +1 -0
  116. package/dist/story-generator/llm-providers/index.js +169 -0
  117. package/dist/story-generator/llm-providers/openai-provider.d.ts +24 -0
  118. package/dist/story-generator/llm-providers/openai-provider.d.ts.map +1 -0
  119. package/dist/story-generator/llm-providers/openai-provider.js +458 -0
  120. package/dist/story-generator/llm-providers/settings-manager.d.ts +75 -0
  121. package/dist/story-generator/llm-providers/settings-manager.d.ts.map +1 -0
  122. package/dist/story-generator/llm-providers/settings-manager.js +173 -0
  123. package/dist/story-generator/llm-providers/story-llm-service.d.ts +79 -0
  124. package/dist/story-generator/llm-providers/story-llm-service.d.ts.map +1 -0
  125. package/dist/story-generator/llm-providers/story-llm-service.js +240 -0
  126. package/dist/story-generator/llm-providers/types.d.ts +153 -0
  127. package/dist/story-generator/llm-providers/types.d.ts.map +1 -0
  128. package/dist/story-generator/llm-providers/types.js +8 -0
  129. package/dist/story-generator/logger.d.ts +14 -0
  130. package/dist/story-generator/logger.d.ts.map +1 -0
  131. package/dist/story-generator/logger.js +96 -29
  132. package/dist/story-generator/postProcessStory.d.ts +6 -0
  133. package/dist/story-generator/postProcessStory.d.ts.map +1 -0
  134. package/dist/story-generator/productionGitignoreManager.d.ts +91 -0
  135. package/dist/story-generator/productionGitignoreManager.d.ts.map +1 -0
  136. package/dist/story-generator/promptGenerator.d.ts +48 -0
  137. package/dist/story-generator/promptGenerator.d.ts.map +1 -0
  138. package/dist/story-generator/promptGenerator.js +186 -1
  139. package/dist/story-generator/storyHistory.d.ts +44 -0
  140. package/dist/story-generator/storyHistory.d.ts.map +1 -0
  141. package/dist/story-generator/storySync.d.ts +68 -0
  142. package/dist/story-generator/storySync.d.ts.map +1 -0
  143. package/dist/story-generator/storyTracker.d.ts +48 -0
  144. package/dist/story-generator/storyTracker.d.ts.map +1 -0
  145. package/dist/story-generator/storyValidator.d.ts +6 -0
  146. package/dist/story-generator/storyValidator.d.ts.map +1 -0
  147. package/dist/story-generator/universalDesignSystemAdapter.d.ts +68 -0
  148. package/dist/story-generator/universalDesignSystemAdapter.d.ts.map +1 -0
  149. package/dist/story-generator/universalDesignSystemAdapter.js +138 -1
  150. package/dist/story-generator/urlRedirectService.d.ts +21 -0
  151. package/dist/story-generator/urlRedirectService.d.ts.map +1 -0
  152. package/dist/story-generator/validateStory.d.ts +19 -0
  153. package/dist/story-generator/validateStory.d.ts.map +1 -0
  154. package/dist/story-generator/validateStory.js +6 -2
  155. package/dist/story-generator/visionPrompts.d.ts +88 -0
  156. package/dist/story-generator/visionPrompts.d.ts.map +1 -0
  157. package/dist/story-generator/visionPrompts.js +462 -0
  158. package/dist/story-ui.config.d.ts +78 -0
  159. package/dist/story-ui.config.d.ts.map +1 -0
  160. package/dist/templates/StoryUI/StoryUIPanel.d.ts +4 -0
  161. package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -0
  162. package/dist/templates/StoryUI/StoryUIPanel.js +1874 -0
  163. package/dist/templates/StoryUI/StoryUIPanel.stories.d.ts +18 -0
  164. package/dist/templates/StoryUI/StoryUIPanel.stories.d.ts.map +1 -0
  165. package/dist/templates/StoryUI/StoryUIPanel.stories.js +37 -0
  166. package/dist/templates/StoryUI/index.d.ts +3 -0
  167. package/dist/templates/StoryUI/index.d.ts.map +1 -0
  168. package/dist/templates/StoryUI/index.js +2 -0
  169. package/package.json +17 -3
  170. package/templates/StoryUI/StoryUIPanel.tsx +1960 -384
  171. package/templates/StoryUI/index.tsx +1 -1
  172. package/templates/StoryUI/manager.tsx +264 -0
  173. package/templates/production-app/.env.example +11 -0
  174. package/templates/production-app/index.html +66 -0
  175. package/templates/production-app/package.json +30 -0
  176. package/templates/production-app/public/favicon.svg +5 -0
  177. package/templates/production-app/src/App.tsx +1157 -0
  178. package/templates/production-app/src/LivePreviewRenderer.tsx +420 -0
  179. package/templates/production-app/src/componentRegistry.ts +315 -0
  180. package/templates/production-app/src/considerations.ts +16 -0
  181. package/templates/production-app/src/index.css +284 -0
  182. package/templates/production-app/src/main.tsx +25 -0
  183. package/templates/production-app/tsconfig.json +32 -0
  184. package/templates/production-app/tsconfig.node.json +11 -0
  185. package/templates/production-app/vite.config.ts +83 -0
  186. package/templates/react-import-rule.json +2 -2
  187. package/dist/index.js +0 -12
  188. package/dist/story-ui.config.loader.js +0 -205
@@ -0,0 +1,414 @@
1
+ /**
2
+ * Claude LLM Provider
3
+ *
4
+ * Implementation of the LLM provider interface for Anthropic's Claude models.
5
+ */
6
+ import { BaseLLMProvider } from './base-provider.js';
7
+ import { logger } from '../logger.js';
8
+ // Claude model definitions - Updated November 2025
9
+ // Based on Anthropic API documentation via Context7
10
+ const CLAUDE_MODELS = [
11
+ // Latest Claude 4.x models (Recommended)
12
+ {
13
+ id: 'claude-opus-4-5-20251101',
14
+ name: 'Claude Opus 4.5',
15
+ provider: 'claude',
16
+ contextWindow: 200000,
17
+ maxOutputTokens: 32000,
18
+ supportsVision: true,
19
+ supportsDocuments: true,
20
+ supportsFunctionCalling: true,
21
+ supportsStreaming: true,
22
+ inputPricePer1kTokens: 0.015,
23
+ outputPricePer1kTokens: 0.075,
24
+ },
25
+ {
26
+ id: 'claude-sonnet-4-5-20250929',
27
+ name: 'Claude Sonnet 4.5',
28
+ provider: 'claude',
29
+ contextWindow: 200000,
30
+ maxOutputTokens: 16000,
31
+ supportsVision: true,
32
+ supportsDocuments: true,
33
+ supportsFunctionCalling: true,
34
+ supportsStreaming: true,
35
+ inputPricePer1kTokens: 0.003,
36
+ outputPricePer1kTokens: 0.015,
37
+ },
38
+ {
39
+ id: 'claude-haiku-4-5-20251001',
40
+ name: 'Claude Haiku 4.5',
41
+ provider: 'claude',
42
+ contextWindow: 200000,
43
+ maxOutputTokens: 8192,
44
+ supportsVision: true,
45
+ supportsDocuments: false,
46
+ supportsFunctionCalling: true,
47
+ supportsStreaming: true,
48
+ inputPricePer1kTokens: 0.0008,
49
+ outputPricePer1kTokens: 0.004,
50
+ },
51
+ // Claude 4.0 models
52
+ {
53
+ id: 'claude-sonnet-4-20250514',
54
+ name: 'Claude Sonnet 4',
55
+ provider: 'claude',
56
+ contextWindow: 200000,
57
+ maxOutputTokens: 16000,
58
+ supportsVision: true,
59
+ supportsDocuments: true,
60
+ supportsFunctionCalling: true,
61
+ supportsStreaming: true,
62
+ inputPricePer1kTokens: 0.003,
63
+ outputPricePer1kTokens: 0.015,
64
+ },
65
+ {
66
+ id: 'claude-opus-4-20250514',
67
+ name: 'Claude Opus 4',
68
+ provider: 'claude',
69
+ contextWindow: 200000,
70
+ maxOutputTokens: 32000,
71
+ supportsVision: true,
72
+ supportsDocuments: true,
73
+ supportsFunctionCalling: true,
74
+ supportsStreaming: true,
75
+ inputPricePer1kTokens: 0.015,
76
+ outputPricePer1kTokens: 0.075,
77
+ },
78
+ // Legacy models (deprecated - use newer versions)
79
+ {
80
+ id: 'claude-3-7-sonnet-20250219',
81
+ name: 'Claude 3.7 Sonnet (Legacy)',
82
+ provider: 'claude',
83
+ contextWindow: 200000,
84
+ maxOutputTokens: 16000,
85
+ supportsVision: true,
86
+ supportsDocuments: true,
87
+ supportsFunctionCalling: true,
88
+ supportsStreaming: true,
89
+ inputPricePer1kTokens: 0.003,
90
+ outputPricePer1kTokens: 0.015,
91
+ },
92
+ {
93
+ id: 'claude-3-5-sonnet-20241022',
94
+ name: 'Claude 3.5 Sonnet (Deprecated)',
95
+ provider: 'claude',
96
+ contextWindow: 200000,
97
+ maxOutputTokens: 8192,
98
+ supportsVision: true,
99
+ supportsDocuments: true,
100
+ supportsFunctionCalling: true,
101
+ supportsStreaming: true,
102
+ inputPricePer1kTokens: 0.003,
103
+ outputPricePer1kTokens: 0.015,
104
+ },
105
+ {
106
+ id: 'claude-3-5-haiku-20241022',
107
+ name: 'Claude 3.5 Haiku (Deprecated)',
108
+ provider: 'claude',
109
+ contextWindow: 200000,
110
+ maxOutputTokens: 8192,
111
+ supportsVision: true,
112
+ supportsDocuments: false,
113
+ supportsFunctionCalling: true,
114
+ supportsStreaming: true,
115
+ inputPricePer1kTokens: 0.0008,
116
+ outputPricePer1kTokens: 0.004,
117
+ },
118
+ ];
119
+ // Default model - Claude Sonnet 4.5 (recommended for agents and coding)
120
+ const DEFAULT_MODEL = 'claude-sonnet-4-5-20250929';
121
+ // API configuration
122
+ const ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';
123
+ const ANTHROPIC_VERSION = '2023-06-01';
124
+ export class ClaudeProvider extends BaseLLMProvider {
125
+ constructor(config) {
126
+ super(config);
127
+ this.name = 'Claude';
128
+ this.type = 'claude';
129
+ this.supportedModels = CLAUDE_MODELS;
130
+ // Set the provider type after base constructor
131
+ this.setProviderType();
132
+ // Set default model if not provided
133
+ if (!this.config.model) {
134
+ this.config.model = DEFAULT_MODEL;
135
+ }
136
+ }
137
+ async chat(messages, options) {
138
+ this.validateMessages(messages);
139
+ this.logRequest(messages, options);
140
+ const apiKey = this.config.apiKey;
141
+ if (!apiKey) {
142
+ throw new Error('Claude API key not configured');
143
+ }
144
+ const model = options?.model || this.config.model;
145
+ const anthropicMessages = this.convertMessages(messages);
146
+ const systemPrompt = this.buildSystemPrompt(options);
147
+ const requestBody = {
148
+ model,
149
+ max_tokens: options?.maxTokens || this.getSelectedModel()?.maxOutputTokens || 4096,
150
+ messages: anthropicMessages,
151
+ };
152
+ // Add optional parameters
153
+ if (systemPrompt) {
154
+ requestBody.system = systemPrompt;
155
+ }
156
+ if (options?.temperature !== undefined) {
157
+ requestBody.temperature = options.temperature;
158
+ }
159
+ if (options?.topP !== undefined) {
160
+ requestBody.top_p = options.topP;
161
+ }
162
+ if (options?.topK !== undefined) {
163
+ requestBody.top_k = options.topK;
164
+ }
165
+ if (options?.stopSequences?.length) {
166
+ requestBody.stop_sequences = options.stopSequences;
167
+ }
168
+ try {
169
+ const response = await fetch(ANTHROPIC_API_URL, {
170
+ method: 'POST',
171
+ headers: {
172
+ 'Content-Type': 'application/json',
173
+ 'x-api-key': apiKey,
174
+ 'anthropic-version': ANTHROPIC_VERSION,
175
+ },
176
+ body: JSON.stringify(requestBody),
177
+ signal: AbortSignal.timeout(this.config.timeout || 120000),
178
+ });
179
+ if (!response.ok) {
180
+ const errorBody = await response.text();
181
+ logger.error('Claude API error response', { status: response.status, body: errorBody });
182
+ throw new Error(`Claude API error: ${response.status} - ${errorBody}`);
183
+ }
184
+ const data = (await response.json());
185
+ const chatResponse = this.convertResponse(data);
186
+ this.logResponse(chatResponse);
187
+ return chatResponse;
188
+ }
189
+ catch (error) {
190
+ if (error instanceof Error && error.name === 'TimeoutError') {
191
+ throw new Error(`Claude API request timed out after ${this.config.timeout}ms`);
192
+ }
193
+ throw error;
194
+ }
195
+ }
196
+ async *chatStream(messages, options) {
197
+ this.validateMessages(messages);
198
+ this.logRequest(messages, options);
199
+ const apiKey = this.config.apiKey;
200
+ if (!apiKey) {
201
+ yield { type: 'error', error: 'Claude API key not configured' };
202
+ return;
203
+ }
204
+ const model = options?.model || this.config.model;
205
+ const anthropicMessages = this.convertMessages(messages);
206
+ const systemPrompt = this.buildSystemPrompt(options);
207
+ const requestBody = {
208
+ model,
209
+ max_tokens: options?.maxTokens || this.getSelectedModel()?.maxOutputTokens || 4096,
210
+ messages: anthropicMessages,
211
+ stream: true,
212
+ };
213
+ if (systemPrompt) {
214
+ requestBody.system = systemPrompt;
215
+ }
216
+ if (options?.temperature !== undefined) {
217
+ requestBody.temperature = options.temperature;
218
+ }
219
+ try {
220
+ const response = await fetch(ANTHROPIC_API_URL, {
221
+ method: 'POST',
222
+ headers: {
223
+ 'Content-Type': 'application/json',
224
+ 'x-api-key': apiKey,
225
+ 'anthropic-version': ANTHROPIC_VERSION,
226
+ },
227
+ body: JSON.stringify(requestBody),
228
+ signal: AbortSignal.timeout(this.config.timeout || 120000),
229
+ });
230
+ if (!response.ok) {
231
+ const errorBody = await response.text();
232
+ yield { type: 'error', error: `Claude API error: ${response.status} - ${errorBody}` };
233
+ return;
234
+ }
235
+ const reader = response.body?.getReader();
236
+ if (!reader) {
237
+ yield { type: 'error', error: 'No response body' };
238
+ return;
239
+ }
240
+ const decoder = new TextDecoder();
241
+ let buffer = '';
242
+ let inputTokens = 0;
243
+ let outputTokens = 0;
244
+ while (true) {
245
+ const { done, value } = await reader.read();
246
+ if (done)
247
+ break;
248
+ buffer += decoder.decode(value, { stream: true });
249
+ const lines = buffer.split('\n');
250
+ buffer = lines.pop() || '';
251
+ for (const line of lines) {
252
+ if (line.startsWith('data: ')) {
253
+ const data = line.slice(6);
254
+ if (data === '[DONE]')
255
+ continue;
256
+ try {
257
+ const event = JSON.parse(data);
258
+ if (event.type === 'content_block_delta' && event.delta?.text) {
259
+ yield { type: 'text', content: event.delta.text };
260
+ }
261
+ else if (event.type === 'message_start' && event.message?.usage) {
262
+ inputTokens = event.message.usage.input_tokens || 0;
263
+ }
264
+ else if (event.type === 'message_delta' && event.usage) {
265
+ outputTokens = event.usage.output_tokens || 0;
266
+ }
267
+ }
268
+ catch {
269
+ // Skip malformed JSON
270
+ }
271
+ }
272
+ }
273
+ }
274
+ yield {
275
+ type: 'done',
276
+ usage: {
277
+ promptTokens: inputTokens,
278
+ completionTokens: outputTokens,
279
+ totalTokens: inputTokens + outputTokens,
280
+ },
281
+ };
282
+ }
283
+ catch (error) {
284
+ yield {
285
+ type: 'error',
286
+ error: error instanceof Error ? error.message : String(error),
287
+ };
288
+ }
289
+ }
290
+ async validateApiKey(apiKey) {
291
+ try {
292
+ // Make a minimal API call to validate the key
293
+ const response = await fetch(ANTHROPIC_API_URL, {
294
+ method: 'POST',
295
+ headers: {
296
+ 'Content-Type': 'application/json',
297
+ 'x-api-key': apiKey,
298
+ 'anthropic-version': ANTHROPIC_VERSION,
299
+ },
300
+ body: JSON.stringify({
301
+ model: 'claude-haiku-4-5-20251001', // Use latest Haiku for fast validation
302
+ max_tokens: 1,
303
+ messages: [{ role: 'user', content: 'Hi' }],
304
+ }),
305
+ signal: AbortSignal.timeout(10000),
306
+ });
307
+ if (response.ok) {
308
+ return {
309
+ valid: true,
310
+ models: this.supportedModels,
311
+ };
312
+ }
313
+ const errorBody = await response.text();
314
+ // Check for specific error types
315
+ if (response.status === 401) {
316
+ return {
317
+ valid: false,
318
+ error: 'Invalid API key',
319
+ };
320
+ }
321
+ return {
322
+ valid: false,
323
+ error: `API validation failed: ${errorBody}`,
324
+ };
325
+ }
326
+ catch (error) {
327
+ return {
328
+ valid: false,
329
+ error: error instanceof Error ? error.message : 'Validation failed',
330
+ };
331
+ }
332
+ }
333
+ // Convert our message format to Anthropic format
334
+ convertMessages(messages) {
335
+ return messages
336
+ .filter(msg => msg.role !== 'system') // System messages handled separately
337
+ .map(msg => ({
338
+ role: msg.role,
339
+ content: this.convertContent(msg.content),
340
+ }));
341
+ }
342
+ convertContent(content) {
343
+ if (typeof content === 'string') {
344
+ return content;
345
+ }
346
+ return content.map(item => {
347
+ if (item.type === 'text') {
348
+ return { type: 'text', text: item.text };
349
+ }
350
+ if (item.type === 'image') {
351
+ const imageContent = item;
352
+ return {
353
+ type: 'image',
354
+ source: {
355
+ type: imageContent.source.type,
356
+ media_type: imageContent.source.mediaType,
357
+ data: imageContent.source.data,
358
+ url: imageContent.source.url,
359
+ },
360
+ };
361
+ }
362
+ // Document type - convert to text representation for now
363
+ if (item.type === 'document') {
364
+ return {
365
+ type: 'text',
366
+ text: `[Document: ${item.source.name || 'unnamed'}]`,
367
+ };
368
+ }
369
+ return { type: 'text', text: '' };
370
+ });
371
+ }
372
+ convertResponse(data) {
373
+ const textContent = data.content
374
+ .filter(block => block.type === 'text')
375
+ .map(block => block.text || '')
376
+ .join('');
377
+ return {
378
+ id: data.id,
379
+ model: data.model,
380
+ content: textContent,
381
+ finishReason: this.mapStopReason(data.stop_reason),
382
+ usage: {
383
+ promptTokens: data.usage.input_tokens,
384
+ completionTokens: data.usage.output_tokens,
385
+ totalTokens: data.usage.input_tokens + data.usage.output_tokens,
386
+ },
387
+ raw: data,
388
+ };
389
+ }
390
+ mapStopReason(stopReason) {
391
+ switch (stopReason) {
392
+ case 'end_turn':
393
+ case 'stop_sequence':
394
+ return 'stop';
395
+ case 'max_tokens':
396
+ return 'length';
397
+ case 'tool_use':
398
+ return 'tool_calls';
399
+ default:
400
+ return 'stop';
401
+ }
402
+ }
403
+ // Token estimation specific to Claude (using cl100k_base-like estimation)
404
+ estimateTokens(text) {
405
+ // Claude uses a similar tokenization to GPT-4
406
+ // Rough estimate: ~4 characters per token for English
407
+ // This is a simple heuristic; actual tokenization may vary
408
+ return Math.ceil(text.length / 4);
409
+ }
410
+ }
411
+ // Factory function
412
+ export function createClaudeProvider(config) {
413
+ return new ClaudeProvider(config);
414
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Gemini LLM Provider
3
+ *
4
+ * Implementation of the LLM provider interface for Google's Gemini 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 GeminiProvider extends BaseLLMProvider {
9
+ readonly name = "Gemini";
10
+ readonly type: ProviderType;
11
+ readonly supportedModels: ModelInfo[];
12
+ constructor(config?: Partial<ProviderConfig>);
13
+ private getApiUrl;
14
+ chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse>;
15
+ chatStream(messages: ChatMessage[], options?: ChatOptions): AsyncIterable<StreamChunk>;
16
+ validateApiKey(apiKey: string): Promise<ValidationResult>;
17
+ private convertMessages;
18
+ private convertContent;
19
+ private convertResponse;
20
+ private mapFinishReason;
21
+ estimateTokens(text: string): number;
22
+ }
23
+ export declare function createGeminiProvider(config?: Partial<ProviderConfig>): GeminiProvider;
24
+ //# sourceMappingURL=gemini-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-provider.d.ts","sourceRoot":"","sources":["../../../story-generator/llm-providers/gemini-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;AAgJrD,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;IAU5C,OAAO,CAAC,SAAS;IAKX,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IA6D1E,UAAU,CACf,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,CAAC,EAAE,WAAW,GACpB,aAAa,CAAC,WAAW,CAAC;IA+GvB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA8C/D,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,cAAc;IAqCtB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,eAAe;IAiBvB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAKrC;AAGD,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAErF"}