nebula-notebook 0.1.1 → 0.2.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.
Files changed (142) hide show
  1. package/README.md +110 -16
  2. package/dist/assets/errorwidget-Wy5ajPiM.js +5 -0
  3. package/dist/assets/fa-brands-400-CEJbCg16.woff +0 -0
  4. package/dist/assets/fa-brands-400-CSYNqBb_.ttf +0 -0
  5. package/dist/assets/fa-brands-400-DnkPfk3o.eot +0 -0
  6. package/dist/assets/fa-brands-400-UxlILjvJ.woff2 +0 -0
  7. package/dist/assets/fa-brands-400-cH1MgKbP.svg +3717 -0
  8. package/dist/assets/fa-regular-400-BhTwtT8w.eot +0 -0
  9. package/dist/assets/fa-regular-400-D1vz6WBx.ttf +0 -0
  10. package/dist/assets/fa-regular-400-DFnMcJPd.woff +0 -0
  11. package/dist/assets/fa-regular-400-DGzu1beS.woff2 +0 -0
  12. package/dist/assets/fa-regular-400-gwj8Pxq-.svg +801 -0
  13. package/dist/assets/fa-solid-900-B4ZZ7kfP.svg +5034 -0
  14. package/dist/assets/fa-solid-900-B6Axprfb.eot +0 -0
  15. package/dist/assets/fa-solid-900-BUswJgRo.woff2 +0 -0
  16. package/dist/assets/fa-solid-900-DOXgCApm.woff +0 -0
  17. package/dist/assets/fa-solid-900-mxuxnBEa.ttf +0 -0
  18. package/dist/assets/index-B_Bs5koo.js +1 -0
  19. package/dist/assets/index-BtWv4MIT.css +7 -0
  20. package/dist/assets/index-DK4nS74r.js +829 -0
  21. package/dist/assets/index-DeQN03nW.js +81 -0
  22. package/dist/assets/index-DzjpmUak.css +32 -0
  23. package/dist/assets/index-g6MjT-VG.js +1 -0
  24. package/dist/assets/services-shim-BirHVsih.js +33 -0
  25. package/dist/assets/viewlist-uomDf7I7.js +1 -0
  26. package/dist/assets/widgets-X7J3NxEn.css +1 -0
  27. package/dist/index.html +2 -2
  28. package/node-server/dist/auth/auth-middleware.js +22 -4
  29. package/node-server/dist/auth/auth-service.js +37 -7
  30. package/node-server/dist/cluster/client-registration.d.ts +12 -1
  31. package/node-server/dist/cluster/client-registration.js +38 -2
  32. package/node-server/dist/cluster/kernel-proxy.js +43 -12
  33. package/node-server/dist/cluster/server-registry.d.ts +17 -0
  34. package/node-server/dist/cluster/server-registry.js +57 -7
  35. package/node-server/dist/discovery/conda-locations.d.ts +73 -0
  36. package/node-server/dist/discovery/conda-locations.js +427 -0
  37. package/node-server/dist/discovery/discovery-service.d.ts +73 -4
  38. package/node-server/dist/discovery/discovery-service.js +211 -127
  39. package/node-server/dist/discovery/types.d.ts +0 -1
  40. package/node-server/dist/discovery/types.js +1 -2
  41. package/node-server/dist/environment.d.ts +12 -0
  42. package/node-server/dist/environment.js +104 -0
  43. package/node-server/dist/fs/fs-service.d.ts +86 -8
  44. package/node-server/dist/fs/fs-service.js +640 -99
  45. package/node-server/dist/fs/notebook-formats/percent.d.ts +25 -0
  46. package/node-server/dist/fs/notebook-formats/percent.js +286 -0
  47. package/node-server/dist/fs/notebook-formats/qmd.d.ts +29 -0
  48. package/node-server/dist/fs/notebook-formats/qmd.js +307 -0
  49. package/node-server/dist/fs/notebook-formats/registry.d.ts +12 -0
  50. package/node-server/dist/fs/notebook-formats/registry.js +77 -0
  51. package/node-server/dist/fs/notebook-formats/types.d.ts +37 -0
  52. package/node-server/dist/fs/notebook-formats/types.js +13 -0
  53. package/node-server/dist/fs/types.d.ts +9 -0
  54. package/node-server/dist/fs/types.js +8 -0
  55. package/node-server/dist/idle-exit.d.ts +52 -0
  56. package/node-server/dist/idle-exit.js +83 -0
  57. package/node-server/dist/index.js +198 -8
  58. package/node-server/dist/kernel/kernel-service.d.ts +130 -2
  59. package/node-server/dist/kernel/kernel-service.js +834 -64
  60. package/node-server/dist/kernel/kernelspec.d.ts +27 -0
  61. package/node-server/dist/kernel/kernelspec.js +75 -4
  62. package/node-server/dist/notebook/headless-handler.d.ts +12 -0
  63. package/node-server/dist/notebook/headless-handler.js +125 -29
  64. package/node-server/dist/notebook/operation-router.js +7 -2
  65. package/node-server/dist/notebook/undoRedoManager.d.ts +12 -1
  66. package/node-server/dist/notebook/undoRedoManager.js +49 -18
  67. package/node-server/dist/output/display-data.js +2 -0
  68. package/node-server/dist/private-tmp.d.ts +14 -0
  69. package/node-server/dist/private-tmp.js +70 -0
  70. package/node-server/dist/routes/autocomplete.d.ts +19 -0
  71. package/node-server/dist/routes/autocomplete.js +294 -0
  72. package/node-server/dist/routes/cluster.js +2 -2
  73. package/node-server/dist/routes/compute.d.ts +8 -0
  74. package/node-server/dist/routes/compute.js +136 -0
  75. package/node-server/dist/routes/fs.js +23 -6
  76. package/node-server/dist/routes/kernel.js +156 -3
  77. package/node-server/dist/routes/notebook.js +37 -3
  78. package/node-server/dist/routes/python.d.ts +1 -2
  79. package/node-server/dist/routes/python.js +139 -3
  80. package/node-server/dist/scheduler/allocation-service.d.ts +63 -0
  81. package/node-server/dist/scheduler/allocation-service.js +285 -0
  82. package/node-server/dist/scheduler/job-template.d.ts +30 -0
  83. package/node-server/dist/scheduler/job-template.js +85 -0
  84. package/node-server/dist/scheduler/mock-scheduler.d.ts +30 -0
  85. package/node-server/dist/scheduler/mock-scheduler.js +125 -0
  86. package/node-server/dist/scheduler/slurm-scheduler.d.ts +31 -0
  87. package/node-server/dist/scheduler/slurm-scheduler.js +406 -0
  88. package/node-server/dist/scheduler/types.d.ts +118 -0
  89. package/node-server/dist/scheduler/types.js +8 -0
  90. package/node-server/dist/scheduler/util.d.ts +7 -0
  91. package/node-server/dist/scheduler/util.js +20 -0
  92. package/node-server/dist/terminal/agent-registry.d.ts +87 -0
  93. package/node-server/dist/terminal/agent-registry.js +246 -0
  94. package/node-server/dist/terminal/binding-store.d.ts +57 -0
  95. package/node-server/dist/terminal/binding-store.js +0 -0
  96. package/node-server/dist/terminal/pty-manager.d.ts +23 -6
  97. package/node-server/dist/terminal/pty-manager.js +138 -19
  98. package/node-server/dist/terminal/server.js +155 -23
  99. package/node-server/dist/terminal/types.d.ts +2 -0
  100. package/node-server/dist/update-check.d.ts +20 -0
  101. package/node-server/dist/update-check.js +114 -0
  102. package/node-server/package.json +2 -0
  103. package/node_modules/nebula-autocomplete/README.md +145 -0
  104. package/node_modules/nebula-autocomplete/dist/backends/claude.d.ts +69 -0
  105. package/node_modules/nebula-autocomplete/dist/backends/claude.js +449 -0
  106. package/node_modules/nebula-autocomplete/dist/backends/codex.d.ts +45 -0
  107. package/node_modules/nebula-autocomplete/dist/backends/codex.js +108 -0
  108. package/node_modules/nebula-autocomplete/dist/client/fetcher.d.ts +16 -0
  109. package/node_modules/nebula-autocomplete/dist/client/fetcher.js +41 -0
  110. package/node_modules/nebula-autocomplete/dist/codemirror/ghostText.d.ts +43 -0
  111. package/node_modules/nebula-autocomplete/dist/codemirror/ghostText.js +175 -0
  112. package/node_modules/nebula-autocomplete/dist/core/engine.d.ts +17 -0
  113. package/node_modules/nebula-autocomplete/dist/core/engine.js +135 -0
  114. package/node_modules/nebula-autocomplete/dist/core/lru.d.ts +7 -0
  115. package/node_modules/nebula-autocomplete/dist/core/lru.js +26 -0
  116. package/node_modules/nebula-autocomplete/dist/core/prompt.d.ts +12 -0
  117. package/node_modules/nebula-autocomplete/dist/core/prompt.js +0 -0
  118. package/node_modules/nebula-autocomplete/dist/core/text.d.ts +53 -0
  119. package/node_modules/nebula-autocomplete/dist/core/text.js +169 -0
  120. package/node_modules/nebula-autocomplete/dist/index.d.ts +7 -0
  121. package/node_modules/nebula-autocomplete/dist/index.js +5 -0
  122. package/node_modules/nebula-autocomplete/dist/server/fastify.d.ts +40 -0
  123. package/node_modules/nebula-autocomplete/dist/server/fastify.js +52 -0
  124. package/node_modules/nebula-autocomplete/dist/transport.d.ts +55 -0
  125. package/node_modules/nebula-autocomplete/dist/transport.js +66 -0
  126. package/node_modules/nebula-autocomplete/dist/types.d.ts +103 -0
  127. package/node_modules/nebula-autocomplete/dist/types.js +1 -0
  128. package/node_modules/nebula-autocomplete/package.json +58 -0
  129. package/node_modules/nebula-autocomplete/server.d.ts +3 -0
  130. package/node_modules/nebula-autocomplete/server.js +3 -0
  131. package/package.json +18 -5
  132. package/scripts/postinstall.cjs +25 -5
  133. package/dist/assets/index-BvrHu37J.js +0 -648
  134. package/dist/assets/index-Dfj_xsKU.css +0 -32
  135. package/node-server/dist/llm/index.d.ts +0 -5
  136. package/node-server/dist/llm/index.js +0 -21
  137. package/node-server/dist/llm/llm-service.d.ts +0 -77
  138. package/node-server/dist/llm/llm-service.js +0 -454
  139. package/node-server/dist/llm/types.d.ts +0 -40
  140. package/node-server/dist/llm/types.js +0 -15
  141. package/node-server/dist/routes/llm.d.ts +0 -8
  142. package/node-server/dist/routes/llm.js +0 -105
@@ -1,454 +0,0 @@
1
- "use strict";
2
- /**
3
- * Multi-Provider LLM Service
4
- *
5
- * Supports Google Gemini, OpenAI, and Anthropic.
6
- * Node.js port of the Python LLMService.
7
- */
8
- var __importDefault = (this && this.__importDefault) || function (mod) {
9
- return (mod && mod.__esModule) ? mod : { "default": mod };
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.llmService = exports.LLMService = void 0;
13
- const genai_1 = require("@google/genai");
14
- const openai_1 = __importDefault(require("openai"));
15
- const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
16
- const types_1 = require("./types");
17
- class LLMService {
18
- googleClient = null;
19
- openaiClient = null;
20
- anthropicClient = null;
21
- /**
22
- * Get or create Google GenAI client
23
- */
24
- getGoogleClient(apiKey) {
25
- if (apiKey) {
26
- // Create new client with provided key (don't cache)
27
- return new genai_1.GoogleGenAI({ apiKey });
28
- }
29
- if (!this.googleClient) {
30
- const envKey = process.env.GEMINI_API_KEY;
31
- if (!envKey) {
32
- throw new Error('GEMINI_API_KEY not found. Configure it in settings or server environment.');
33
- }
34
- this.googleClient = new genai_1.GoogleGenAI({ apiKey: envKey });
35
- }
36
- return this.googleClient;
37
- }
38
- /**
39
- * Get or create OpenAI client
40
- */
41
- getOpenaiClient(apiKey) {
42
- if (apiKey) {
43
- return new openai_1.default({ apiKey });
44
- }
45
- if (!this.openaiClient) {
46
- const envKey = process.env.OPENAI_API_KEY;
47
- if (!envKey) {
48
- throw new Error('OPENAI_API_KEY not found. Configure it in settings or server environment.');
49
- }
50
- this.openaiClient = new openai_1.default({ apiKey: envKey });
51
- }
52
- return this.openaiClient;
53
- }
54
- /**
55
- * Get or create Anthropic client
56
- */
57
- getAnthropicClient(apiKey) {
58
- if (apiKey) {
59
- return new sdk_1.default({ apiKey });
60
- }
61
- if (!this.anthropicClient) {
62
- const envKey = process.env.ANTHROPIC_API_KEY;
63
- if (!envKey) {
64
- throw new Error('ANTHROPIC_API_KEY not found. Configure it in settings or server environment.');
65
- }
66
- this.anthropicClient = new sdk_1.default({ apiKey: envKey });
67
- }
68
- return this.anthropicClient;
69
- }
70
- /**
71
- * Get available providers based on configured API keys
72
- */
73
- getAvailableProviders() {
74
- const available = {};
75
- if (process.env.GEMINI_API_KEY) {
76
- available.google = types_1.AVAILABLE_MODELS.google;
77
- }
78
- if (process.env.OPENAI_API_KEY) {
79
- available.openai = types_1.AVAILABLE_MODELS.openai;
80
- }
81
- if (process.env.ANTHROPIC_API_KEY) {
82
- available.anthropic = types_1.AVAILABLE_MODELS.anthropic;
83
- }
84
- return available;
85
- }
86
- /**
87
- * Normalize config with defaults
88
- */
89
- normalizeConfig(config) {
90
- return {
91
- provider: config.provider,
92
- model: config.model,
93
- temperature: config.temperature ?? types_1.DEFAULT_TEMPERATURE,
94
- maxTokens: config.maxTokens ?? types_1.DEFAULT_MAX_TOKENS,
95
- apiKey: config.apiKey,
96
- };
97
- }
98
- /**
99
- * Repair common JSON formatting issues
100
- */
101
- repairJson(s) {
102
- let result = s;
103
- // Replace : 'value' with : "value"
104
- result = result.replace(/:\s*'([^']*)'/g, ': "$1"');
105
- // Remove trailing commas before } or ]
106
- result = result.replace(/,(\s*[}\]])/g, '$1');
107
- return result;
108
- }
109
- /**
110
- * Parse JSON with automatic repair on failure
111
- */
112
- parseJsonWithRepair(s) {
113
- try {
114
- return JSON.parse(s);
115
- }
116
- catch {
117
- try {
118
- const repaired = this.repairJson(s);
119
- return JSON.parse(repaired);
120
- }
121
- catch {
122
- throw new Error('Failed to parse JSON');
123
- }
124
- }
125
- }
126
- /**
127
- * Extract JSON from a response that may contain markdown code blocks
128
- */
129
- extractJsonFromResponse(response) {
130
- // Try to find JSON in code block first
131
- const codeBlockMatch = response.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
132
- if (codeBlockMatch) {
133
- return this.parseJsonWithRepair(codeBlockMatch[1]);
134
- }
135
- // Try to find raw JSON object
136
- const jsonMatch = response.match(/\{[\s\S]*\}/);
137
- if (jsonMatch) {
138
- return this.parseJsonWithRepair(jsonMatch[0]);
139
- }
140
- throw new Error('No JSON found in response');
141
- }
142
- /**
143
- * Generate response from Google Gemini
144
- */
145
- async generateGoogle(prompt, systemPrompt, config, images) {
146
- const client = this.getGoogleClient(config.apiKey);
147
- // Build content parts
148
- const contents = [prompt];
149
- if (images) {
150
- for (const img of images) {
151
- contents.push({
152
- inlineData: {
153
- mimeType: img.mimeType || 'image/png',
154
- data: img.data,
155
- },
156
- });
157
- }
158
- }
159
- const response = await client.models.generateContent({
160
- model: config.model,
161
- contents,
162
- config: {
163
- systemInstruction: systemPrompt,
164
- temperature: config.temperature,
165
- maxOutputTokens: config.maxTokens,
166
- },
167
- });
168
- return response.text || '';
169
- }
170
- /**
171
- * Generate response from OpenAI
172
- */
173
- async generateOpenai(prompt, systemPrompt, config, images) {
174
- const client = this.getOpenaiClient(config.apiKey);
175
- const messages = [
176
- { role: 'system', content: systemPrompt },
177
- ];
178
- // Build user message content
179
- if (images && images.length > 0) {
180
- const content = [
181
- { type: 'text', text: prompt },
182
- ];
183
- for (const img of images) {
184
- content.push({
185
- type: 'image_url',
186
- image_url: {
187
- url: `data:${img.mimeType || 'image/png'};base64,${img.data}`,
188
- },
189
- });
190
- }
191
- messages.push({ role: 'user', content });
192
- }
193
- else {
194
- messages.push({ role: 'user', content: prompt });
195
- }
196
- const response = await client.chat.completions.create({
197
- model: config.model,
198
- messages,
199
- temperature: config.temperature,
200
- max_completion_tokens: config.maxTokens,
201
- });
202
- return response.choices[0]?.message?.content || '';
203
- }
204
- /**
205
- * Generate response from Anthropic Claude
206
- */
207
- async generateAnthropic(prompt, systemPrompt, config, images) {
208
- const client = this.getAnthropicClient(config.apiKey);
209
- // Build user message content
210
- let content;
211
- if (images && images.length > 0) {
212
- const parts = [];
213
- for (const img of images) {
214
- parts.push({
215
- type: 'image',
216
- source: {
217
- type: 'base64',
218
- media_type: img.mimeType || 'image/png',
219
- data: img.data,
220
- },
221
- });
222
- }
223
- parts.push({ type: 'text', text: prompt });
224
- content = parts;
225
- }
226
- else {
227
- content = prompt;
228
- }
229
- const response = await client.messages.create({
230
- model: config.model,
231
- max_tokens: config.maxTokens,
232
- system: systemPrompt,
233
- messages: [{ role: 'user', content }],
234
- temperature: config.temperature,
235
- });
236
- const textBlock = response.content.find(c => c.type === 'text');
237
- return textBlock && 'text' in textBlock ? textBlock.text : '';
238
- }
239
- /**
240
- * Generate a response from the LLM
241
- */
242
- async generate(options) {
243
- const { prompt, systemPrompt, config, images } = options;
244
- const normalizedConfig = this.normalizeConfig(config);
245
- switch (config.provider) {
246
- case 'google':
247
- return this.generateGoogle(prompt, systemPrompt, normalizedConfig, images);
248
- case 'openai':
249
- return this.generateOpenai(prompt, systemPrompt, normalizedConfig, images);
250
- case 'anthropic':
251
- return this.generateAnthropic(prompt, systemPrompt, normalizedConfig, images);
252
- default:
253
- throw new Error(`Unknown provider: ${config.provider}`);
254
- }
255
- }
256
- /**
257
- * Generate structured JSON response
258
- */
259
- async generateStructured(options) {
260
- const { prompt, systemPrompt, config } = options;
261
- const normalizedConfig = this.normalizeConfig(config);
262
- switch (config.provider) {
263
- case 'google':
264
- return this.generateStructuredGoogle(prompt, systemPrompt, normalizedConfig);
265
- case 'openai':
266
- return this.generateStructuredOpenai(prompt, systemPrompt, normalizedConfig);
267
- case 'anthropic':
268
- return this.generateStructuredAnthropic(prompt, systemPrompt, normalizedConfig);
269
- default:
270
- throw new Error(`Unknown provider: ${config.provider}`);
271
- }
272
- }
273
- async generateStructuredGoogle(prompt, systemPrompt, config) {
274
- const client = this.getGoogleClient(config.apiKey);
275
- const response = await client.models.generateContent({
276
- model: config.model,
277
- contents: [prompt],
278
- config: {
279
- systemInstruction: systemPrompt,
280
- temperature: config.temperature,
281
- maxOutputTokens: config.maxTokens,
282
- responseMimeType: 'application/json',
283
- },
284
- });
285
- return this.extractJsonFromResponse(response.text || '');
286
- }
287
- async generateStructuredOpenai(prompt, systemPrompt, config) {
288
- const client = this.getOpenaiClient(config.apiKey);
289
- const response = await client.chat.completions.create({
290
- model: config.model,
291
- messages: [
292
- { role: 'system', content: systemPrompt },
293
- { role: 'user', content: prompt },
294
- ],
295
- temperature: config.temperature,
296
- max_completion_tokens: config.maxTokens,
297
- response_format: { type: 'json_object' },
298
- });
299
- const content = response.choices[0]?.message?.content || '{}';
300
- return JSON.parse(content);
301
- }
302
- async generateStructuredAnthropic(prompt, systemPrompt, config) {
303
- const client = this.getAnthropicClient(config.apiKey);
304
- // Anthropic doesn't have native JSON mode, so we enforce via prompt
305
- const enhancedSystem = systemPrompt +
306
- '\n\nIMPORTANT: Respond with ONLY a valid JSON object. No markdown, no explanation outside the JSON.';
307
- const response = await client.messages.create({
308
- model: config.model,
309
- max_tokens: config.maxTokens,
310
- system: enhancedSystem,
311
- messages: [{ role: 'user', content: prompt }],
312
- temperature: config.temperature,
313
- });
314
- const textBlock = response.content.find(c => c.type === 'text');
315
- const text = textBlock && 'text' in textBlock ? textBlock.text : '';
316
- return this.extractJsonFromResponse(text);
317
- }
318
- /**
319
- * Chat with conversation history
320
- */
321
- async chat(options) {
322
- const { message, history, systemPrompt, config, images } = options;
323
- const normalizedConfig = this.normalizeConfig(config);
324
- switch (config.provider) {
325
- case 'google':
326
- return this.chatGoogle(message, history, systemPrompt, normalizedConfig, images);
327
- case 'openai':
328
- return this.chatOpenai(message, history, systemPrompt, normalizedConfig, images);
329
- case 'anthropic':
330
- return this.chatAnthropic(message, history, systemPrompt, normalizedConfig, images);
331
- default:
332
- throw new Error(`Unknown provider: ${config.provider}`);
333
- }
334
- }
335
- async chatGoogle(message, history, systemPrompt, config, images) {
336
- const client = this.getGoogleClient(config.apiKey);
337
- // Convert history to Gemini format
338
- const contents = [];
339
- for (const msg of history) {
340
- contents.push({
341
- role: msg.role === 'user' ? 'user' : 'model',
342
- parts: [{ text: msg.content }],
343
- });
344
- }
345
- // Add current message with images
346
- const currentParts = [
347
- { text: message },
348
- ];
349
- if (images) {
350
- for (const img of images) {
351
- currentParts.push({
352
- inlineData: {
353
- mimeType: img.mimeType || 'image/png',
354
- data: img.data,
355
- },
356
- });
357
- }
358
- }
359
- contents.push({
360
- role: 'user',
361
- parts: currentParts,
362
- });
363
- const response = await client.models.generateContent({
364
- model: config.model,
365
- contents,
366
- config: {
367
- systemInstruction: systemPrompt,
368
- temperature: config.temperature,
369
- maxOutputTokens: config.maxTokens,
370
- },
371
- });
372
- return response.text || '';
373
- }
374
- async chatOpenai(message, history, systemPrompt, config, images) {
375
- const client = this.getOpenaiClient(config.apiKey);
376
- const messages = [
377
- { role: 'system', content: systemPrompt },
378
- ];
379
- // Add history
380
- for (const msg of history) {
381
- messages.push({
382
- role: msg.role,
383
- content: msg.content,
384
- });
385
- }
386
- // Add current message with images
387
- if (images && images.length > 0) {
388
- const content = [
389
- { type: 'text', text: message },
390
- ];
391
- for (const img of images) {
392
- content.push({
393
- type: 'image_url',
394
- image_url: {
395
- url: `data:${img.mimeType || 'image/png'};base64,${img.data}`,
396
- },
397
- });
398
- }
399
- messages.push({ role: 'user', content });
400
- }
401
- else {
402
- messages.push({ role: 'user', content: message });
403
- }
404
- const response = await client.chat.completions.create({
405
- model: config.model,
406
- messages,
407
- temperature: config.temperature,
408
- max_completion_tokens: config.maxTokens,
409
- });
410
- return response.choices[0]?.message?.content || '';
411
- }
412
- async chatAnthropic(message, history, systemPrompt, config, images) {
413
- const client = this.getAnthropicClient(config.apiKey);
414
- const messages = [];
415
- // Add history
416
- for (const msg of history) {
417
- messages.push({
418
- role: msg.role,
419
- content: msg.content,
420
- });
421
- }
422
- // Add current message with images
423
- if (images && images.length > 0) {
424
- const parts = [];
425
- for (const img of images) {
426
- parts.push({
427
- type: 'image',
428
- source: {
429
- type: 'base64',
430
- media_type: img.mimeType || 'image/png',
431
- data: img.data,
432
- },
433
- });
434
- }
435
- parts.push({ type: 'text', text: message });
436
- messages.push({ role: 'user', content: parts });
437
- }
438
- else {
439
- messages.push({ role: 'user', content: message });
440
- }
441
- const response = await client.messages.create({
442
- model: config.model,
443
- max_tokens: config.maxTokens,
444
- system: systemPrompt,
445
- messages,
446
- temperature: config.temperature,
447
- });
448
- const textBlock = response.content.find(c => c.type === 'text');
449
- return textBlock && 'text' in textBlock ? textBlock.text : '';
450
- }
451
- }
452
- exports.LLMService = LLMService;
453
- // Global instance
454
- exports.llmService = new LLMService();
@@ -1,40 +0,0 @@
1
- /**
2
- * LLM Service Types
3
- */
4
- export type LLMProvider = 'google' | 'openai' | 'anthropic';
5
- export interface LLMConfig {
6
- provider: LLMProvider;
7
- model: string;
8
- temperature?: number;
9
- maxTokens?: number;
10
- apiKey?: string;
11
- }
12
- export interface ImageInput {
13
- mimeType: string;
14
- data: string;
15
- }
16
- export interface ChatMessage {
17
- role: 'user' | 'assistant';
18
- content: string;
19
- }
20
- export interface GenerateOptions {
21
- prompt: string;
22
- systemPrompt: string;
23
- config: LLMConfig;
24
- images?: ImageInput[];
25
- }
26
- export interface ChatOptions {
27
- message: string;
28
- history: ChatMessage[];
29
- systemPrompt: string;
30
- config: LLMConfig;
31
- images?: ImageInput[];
32
- }
33
- export interface GenerateStructuredOptions {
34
- prompt: string;
35
- systemPrompt: string;
36
- config: LLMConfig;
37
- }
38
- export declare const AVAILABLE_MODELS: Record<LLMProvider, string[]>;
39
- export declare const DEFAULT_MAX_TOKENS = 4096;
40
- export declare const DEFAULT_TEMPERATURE = 0.2;
@@ -1,15 +0,0 @@
1
- "use strict";
2
- /**
3
- * LLM Service Types
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_TEMPERATURE = exports.DEFAULT_MAX_TOKENS = exports.AVAILABLE_MODELS = void 0;
7
- // Available models per provider (Dec 2025)
8
- exports.AVAILABLE_MODELS = {
9
- google: ['gemini-3.0-flash', 'gemini-3.0-pro', 'gemini-2.5-flash'],
10
- openai: ['gpt-5.2', 'gpt-5-mini', 'gpt-4o'],
11
- anthropic: ['claude-opus-4-5-20251101', 'claude-sonnet-4-5-20250929', 'claude-haiku-4-5-20251101'],
12
- };
13
- // Default configuration
14
- exports.DEFAULT_MAX_TOKENS = 4096;
15
- exports.DEFAULT_TEMPERATURE = 0.2;
@@ -1,8 +0,0 @@
1
- /**
2
- * LLM API Routes
3
- */
4
- import { FastifyInstance } from 'fastify';
5
- import { LLMService } from '../llm/llm-service';
6
- declare const llmService: LLMService;
7
- export default function llmRoutes(fastify: FastifyInstance): Promise<void>;
8
- export { llmService };
@@ -1,105 +0,0 @@
1
- "use strict";
2
- /**
3
- * LLM API Routes
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.llmService = void 0;
7
- exports.default = llmRoutes;
8
- const llm_service_1 = require("../llm/llm-service");
9
- const llmService = new llm_service_1.LLMService();
10
- exports.llmService = llmService;
11
- async function llmRoutes(fastify) {
12
- /**
13
- * List available LLM providers and models
14
- */
15
- fastify.get('/llm/providers', async (_request, reply) => {
16
- const providers = llmService.getAvailableProviders();
17
- return reply.send({ providers });
18
- });
19
- /**
20
- * Generate text/code from LLM
21
- */
22
- fastify.post('/llm/generate', async (request, reply) => {
23
- try {
24
- const { prompt, system_prompt, provider = 'google', model = 'gemini-2.5-flash', temperature = 0.2, images, } = request.body;
25
- // Check for API key from header
26
- const apiKey = request.headers['x-api-key'];
27
- const apiProvider = request.headers['x-api-provider'];
28
- const response = await llmService.generate({
29
- prompt,
30
- systemPrompt: system_prompt,
31
- config: {
32
- provider: provider,
33
- model,
34
- temperature,
35
- apiKey: apiProvider === provider ? apiKey : undefined,
36
- },
37
- images: images,
38
- });
39
- return reply.send({ response });
40
- }
41
- catch (err) {
42
- const message = err instanceof Error ? err.message : 'Unknown error';
43
- return reply.code(500).send({ detail: message });
44
- }
45
- });
46
- /**
47
- * Generate structured JSON response from LLM
48
- */
49
- fastify.post('/llm/generate-structured', async (request, reply) => {
50
- try {
51
- const { prompt, system_prompt, provider = 'google', model = 'gemini-2.5-flash', temperature = 0.2, } = request.body;
52
- // Check for API key from header
53
- const apiKey = request.headers['x-api-key'];
54
- const apiProvider = request.headers['x-api-provider'];
55
- const response = await llmService.generateStructured({
56
- prompt,
57
- systemPrompt: system_prompt,
58
- config: {
59
- provider: provider,
60
- model,
61
- temperature,
62
- apiKey: apiProvider === provider ? apiKey : undefined,
63
- },
64
- });
65
- return reply.send({ response });
66
- }
67
- catch (err) {
68
- const message = err instanceof Error ? err.message : 'Unknown error';
69
- return reply.code(500).send({ detail: message });
70
- }
71
- });
72
- /**
73
- * Chat with LLM including history
74
- */
75
- fastify.post('/llm/chat', async (request, reply) => {
76
- try {
77
- const { message, history = [], system_prompt, provider = 'google', model = 'gemini-2.5-flash', temperature = 0.2, images, } = request.body;
78
- // Check for API key from header
79
- const apiKey = request.headers['x-api-key'];
80
- const apiProvider = request.headers['x-api-provider'];
81
- // Convert history format
82
- const chatHistory = history.map((h) => ({
83
- role: h.role,
84
- content: h.content,
85
- }));
86
- const response = await llmService.chat({
87
- message,
88
- history: chatHistory,
89
- systemPrompt: system_prompt,
90
- config: {
91
- provider: provider,
92
- model,
93
- temperature,
94
- apiKey: apiProvider === provider ? apiKey : undefined,
95
- },
96
- images: images,
97
- });
98
- return reply.send({ response });
99
- }
100
- catch (err) {
101
- const message = err instanceof Error ? err.message : 'Unknown error';
102
- return reply.code(500).send({ detail: message });
103
- }
104
- });
105
- }