hazo_llm_api 1.0.2 → 1.0.4

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 (151) hide show
  1. package/README.md +4 -4
  2. package/package.json +1 -1
  3. package/techdoc.md +2 -2
  4. package/dist/components/hazo_llm_prompt_config/hazo_llm_prompt_config.d.ts +0 -16
  5. package/dist/components/hazo_llm_prompt_config/hazo_llm_prompt_config.d.ts.map +0 -1
  6. package/dist/components/hazo_llm_prompt_config/hazo_llm_prompt_config.js +0 -258
  7. package/dist/components/hazo_llm_prompt_config/hazo_llm_prompt_config.js.map +0 -1
  8. package/dist/components/hazo_llm_prompt_config/index.d.ts +0 -8
  9. package/dist/components/hazo_llm_prompt_config/index.d.ts.map +0 -1
  10. package/dist/components/hazo_llm_prompt_config/index.js +0 -7
  11. package/dist/components/hazo_llm_prompt_config/index.js.map +0 -1
  12. package/dist/components/hazo_llm_prompt_config/types.d.ts +0 -74
  13. package/dist/components/hazo_llm_prompt_config/types.d.ts.map +0 -1
  14. package/dist/components/hazo_llm_prompt_config/types.js +0 -8
  15. package/dist/components/hazo_llm_prompt_config/types.js.map +0 -1
  16. package/dist/components/index.d.ts +0 -7
  17. package/dist/components/index.d.ts.map +0 -1
  18. package/dist/components/index.js +0 -7
  19. package/dist/components/index.js.map +0 -1
  20. package/dist/components/layout/index.d.ts +0 -7
  21. package/dist/components/layout/index.d.ts.map +0 -1
  22. package/dist/components/layout/index.js +0 -7
  23. package/dist/components/layout/index.js.map +0 -1
  24. package/dist/components/layout/layout.d.ts +0 -21
  25. package/dist/components/layout/layout.d.ts.map +0 -1
  26. package/dist/components/layout/layout.js +0 -18
  27. package/dist/components/layout/layout.js.map +0 -1
  28. package/dist/index.d.ts +0 -11
  29. package/dist/index.d.ts.map +0 -1
  30. package/dist/index.js +0 -13
  31. package/dist/index.js.map +0 -1
  32. package/dist/lib/config/config_parser.d.ts +0 -131
  33. package/dist/lib/config/config_parser.d.ts.map +0 -1
  34. package/dist/lib/config/config_parser.js +0 -297
  35. package/dist/lib/config/config_parser.js.map +0 -1
  36. package/dist/lib/config/index.d.ts +0 -8
  37. package/dist/lib/config/index.d.ts.map +0 -1
  38. package/dist/lib/config/index.js +0 -22
  39. package/dist/lib/config/index.js.map +0 -1
  40. package/dist/lib/config/provider_loader.d.ts +0 -113
  41. package/dist/lib/config/provider_loader.d.ts.map +0 -1
  42. package/dist/lib/config/provider_loader.js +0 -169
  43. package/dist/lib/config/provider_loader.js.map +0 -1
  44. package/dist/lib/database/index.d.ts +0 -8
  45. package/dist/lib/database/index.d.ts.map +0 -1
  46. package/dist/lib/database/index.js +0 -8
  47. package/dist/lib/database/index.js.map +0 -1
  48. package/dist/lib/database/init_database.d.ts +0 -62
  49. package/dist/lib/database/init_database.d.ts.map +0 -1
  50. package/dist/lib/database/init_database.js +0 -436
  51. package/dist/lib/database/init_database.js.map +0 -1
  52. package/dist/lib/database/utils.d.ts +0 -50
  53. package/dist/lib/database/utils.d.ts.map +0 -1
  54. package/dist/lib/database/utils.js +0 -78
  55. package/dist/lib/database/utils.js.map +0 -1
  56. package/dist/lib/index.d.ts +0 -14
  57. package/dist/lib/index.d.ts.map +0 -1
  58. package/dist/lib/index.js +0 -17
  59. package/dist/lib/index.js.map +0 -1
  60. package/dist/lib/llm_api/hazo_llm_image_image.d.ts +0 -26
  61. package/dist/lib/llm_api/hazo_llm_image_image.d.ts.map +0 -1
  62. package/dist/lib/llm_api/hazo_llm_image_image.js +0 -92
  63. package/dist/lib/llm_api/hazo_llm_image_image.js.map +0 -1
  64. package/dist/lib/llm_api/hazo_llm_image_image_text.d.ts +0 -26
  65. package/dist/lib/llm_api/hazo_llm_image_image_text.d.ts.map +0 -1
  66. package/dist/lib/llm_api/hazo_llm_image_image_text.js +0 -220
  67. package/dist/lib/llm_api/hazo_llm_image_image_text.js.map +0 -1
  68. package/dist/lib/llm_api/hazo_llm_image_text.d.ts +0 -20
  69. package/dist/lib/llm_api/hazo_llm_image_text.d.ts.map +0 -1
  70. package/dist/lib/llm_api/hazo_llm_image_text.js +0 -76
  71. package/dist/lib/llm_api/hazo_llm_image_text.js.map +0 -1
  72. package/dist/lib/llm_api/hazo_llm_text_image.d.ts +0 -20
  73. package/dist/lib/llm_api/hazo_llm_text_image.d.ts.map +0 -1
  74. package/dist/lib/llm_api/hazo_llm_text_image.js +0 -67
  75. package/dist/lib/llm_api/hazo_llm_text_image.js.map +0 -1
  76. package/dist/lib/llm_api/hazo_llm_text_image_text.d.ts +0 -26
  77. package/dist/lib/llm_api/hazo_llm_text_image_text.d.ts.map +0 -1
  78. package/dist/lib/llm_api/hazo_llm_text_image_text.js +0 -152
  79. package/dist/lib/llm_api/hazo_llm_text_image_text.js.map +0 -1
  80. package/dist/lib/llm_api/hazo_llm_text_text.d.ts +0 -20
  81. package/dist/lib/llm_api/hazo_llm_text_text.d.ts.map +0 -1
  82. package/dist/lib/llm_api/hazo_llm_text_text.js +0 -89
  83. package/dist/lib/llm_api/hazo_llm_text_text.js.map +0 -1
  84. package/dist/lib/llm_api/index.d.ts +0 -99
  85. package/dist/lib/llm_api/index.d.ts.map +0 -1
  86. package/dist/lib/llm_api/index.js +0 -952
  87. package/dist/lib/llm_api/index.js.map +0 -1
  88. package/dist/lib/llm_api/provider_helper.d.ts +0 -107
  89. package/dist/lib/llm_api/provider_helper.d.ts.map +0 -1
  90. package/dist/lib/llm_api/provider_helper.js +0 -159
  91. package/dist/lib/llm_api/provider_helper.js.map +0 -1
  92. package/dist/lib/llm_api/types.d.ts +0 -352
  93. package/dist/lib/llm_api/types.d.ts.map +0 -1
  94. package/dist/lib/llm_api/types.js +0 -8
  95. package/dist/lib/llm_api/types.js.map +0 -1
  96. package/dist/lib/prompts/get_prompt.d.ts +0 -50
  97. package/dist/lib/prompts/get_prompt.d.ts.map +0 -1
  98. package/dist/lib/prompts/get_prompt.js +0 -232
  99. package/dist/lib/prompts/get_prompt.js.map +0 -1
  100. package/dist/lib/prompts/index.d.ts +0 -9
  101. package/dist/lib/prompts/index.d.ts.map +0 -1
  102. package/dist/lib/prompts/index.js +0 -9
  103. package/dist/lib/prompts/index.js.map +0 -1
  104. package/dist/lib/prompts/prompt_cache.d.ts +0 -151
  105. package/dist/lib/prompts/prompt_cache.d.ts.map +0 -1
  106. package/dist/lib/prompts/prompt_cache.js +0 -276
  107. package/dist/lib/prompts/prompt_cache.js.map +0 -1
  108. package/dist/lib/prompts/substitute_variables.d.ts +0 -38
  109. package/dist/lib/prompts/substitute_variables.d.ts.map +0 -1
  110. package/dist/lib/prompts/substitute_variables.js +0 -175
  111. package/dist/lib/prompts/substitute_variables.js.map +0 -1
  112. package/dist/lib/providers/gemini/gemini_client.d.ts +0 -25
  113. package/dist/lib/providers/gemini/gemini_client.d.ts.map +0 -1
  114. package/dist/lib/providers/gemini/gemini_client.js +0 -235
  115. package/dist/lib/providers/gemini/gemini_client.js.map +0 -1
  116. package/dist/lib/providers/gemini/gemini_provider.d.ts +0 -111
  117. package/dist/lib/providers/gemini/gemini_provider.d.ts.map +0 -1
  118. package/dist/lib/providers/gemini/gemini_provider.js +0 -431
  119. package/dist/lib/providers/gemini/gemini_provider.js.map +0 -1
  120. package/dist/lib/providers/gemini/index.d.ts +0 -8
  121. package/dist/lib/providers/gemini/index.d.ts.map +0 -1
  122. package/dist/lib/providers/gemini/index.js +0 -8
  123. package/dist/lib/providers/gemini/index.js.map +0 -1
  124. package/dist/lib/providers/index.d.ts +0 -8
  125. package/dist/lib/providers/index.d.ts.map +0 -1
  126. package/dist/lib/providers/index.js +0 -8
  127. package/dist/lib/providers/index.js.map +0 -1
  128. package/dist/lib/providers/qwen/index.d.ts +0 -8
  129. package/dist/lib/providers/qwen/index.d.ts.map +0 -1
  130. package/dist/lib/providers/qwen/index.js +0 -8
  131. package/dist/lib/providers/qwen/index.js.map +0 -1
  132. package/dist/lib/providers/qwen/qwen_client.d.ts +0 -154
  133. package/dist/lib/providers/qwen/qwen_client.d.ts.map +0 -1
  134. package/dist/lib/providers/qwen/qwen_client.js +0 -1002
  135. package/dist/lib/providers/qwen/qwen_client.js.map +0 -1
  136. package/dist/lib/providers/qwen/qwen_provider.d.ts +0 -139
  137. package/dist/lib/providers/qwen/qwen_provider.d.ts.map +0 -1
  138. package/dist/lib/providers/qwen/qwen_provider.js +0 -304
  139. package/dist/lib/providers/qwen/qwen_provider.js.map +0 -1
  140. package/dist/lib/providers/registry.d.ts +0 -66
  141. package/dist/lib/providers/registry.d.ts.map +0 -1
  142. package/dist/lib/providers/registry.js +0 -158
  143. package/dist/lib/providers/registry.js.map +0 -1
  144. package/dist/lib/providers/types.d.ts +0 -95
  145. package/dist/lib/providers/types.d.ts.map +0 -1
  146. package/dist/lib/providers/types.js +0 -19
  147. package/dist/lib/providers/types.js.map +0 -1
  148. package/dist/server.d.ts +0 -21
  149. package/dist/server.d.ts.map +0 -1
  150. package/dist/server.js +0 -32
  151. package/dist/server.js.map +0 -1
@@ -1,952 +0,0 @@
1
- /**
2
- * LLM API Module
3
- *
4
- * Main entry point for the LLM API functionality.
5
- * Provides initialization and specialized LLM functions:
6
- * - hazo_llm_text_text: Text input → Text output
7
- * - hazo_llm_image_text: Image input → Text output
8
- * - hazo_llm_text_image: Text input → Image output
9
- * - hazo_llm_image_image: Image input → Image output
10
- * - hazo_llm_text_image_text: Text → Image → Text (chained)
11
- * - hazo_llm_image_image_text: Images → Image → Text (chained)
12
- *
13
- * Database is auto-initialized on module import using config defaults.
14
- */
15
- import { initialize_database, get_database } from '../database/init_database.js';
16
- import { hazo_llm_text_text as hazo_llm_text_text_internal } from './hazo_llm_text_text.js';
17
- import { hazo_llm_image_text as hazo_llm_image_text_internal } from './hazo_llm_image_text.js';
18
- import { hazo_llm_text_image as hazo_llm_text_image_internal } from './hazo_llm_text_image.js';
19
- import { hazo_llm_image_image as hazo_llm_image_image_internal } from './hazo_llm_image_image.js';
20
- import { hazo_llm_text_image_text as hazo_llm_text_image_text_internal } from './hazo_llm_text_image_text.js';
21
- import { hazo_llm_image_image_text as hazo_llm_image_image_text_internal } from './hazo_llm_image_image_text.js';
22
- import { register_provider, set_enabled_llms, set_primary_llm, get_primary_llm, get_registered_providers, } from '../providers/registry.js';
23
- import { GeminiProvider } from '../providers/gemini/index.js';
24
- import { QwenProvider } from '../providers/qwen/index.js';
25
- import { SERVICE_TYPES } from '../providers/types.js';
26
- import * as fs from 'fs';
27
- import * as path from 'path';
28
- import * as ini from 'ini';
29
- // =============================================================================
30
- // Module State
31
- // =============================================================================
32
- let initialized = false;
33
- let db_auto_initialized = false;
34
- let current_config = null;
35
- // =============================================================================
36
- // Default Logger (for auto-initialization)
37
- // =============================================================================
38
- /**
39
- * Default console logger for auto-initialization when no custom logger provided
40
- */
41
- const default_logger = {
42
- error: (message, meta) => {
43
- console.error(`[HAZO_LLM_API ERROR] ${message}`, meta ? JSON.stringify(meta, null, 2) : '');
44
- },
45
- info: (message, meta) => {
46
- console.log(`[HAZO_LLM_API INFO] ${message}`, meta ? JSON.stringify(meta, null, 2) : '');
47
- },
48
- warn: (message, meta) => {
49
- console.warn(`[HAZO_LLM_API WARN] ${message}`, meta ? JSON.stringify(meta, null, 2) : '');
50
- },
51
- debug: (message, meta) => {
52
- console.debug(`[HAZO_LLM_API DEBUG] ${message}`, meta ? JSON.stringify(meta, null, 2) : '');
53
- },
54
- };
55
- // =============================================================================
56
- // Config Reader
57
- // =============================================================================
58
- /**
59
- * Find the config file path
60
- * Searches in current directory and parent directories
61
- * @returns The path to the config file or null if not found
62
- */
63
- function find_config_file() {
64
- const config_filename = 'hazo_llm_api_config.ini';
65
- // Search paths: current dir, parent dir, grandparent dir
66
- const search_paths = [
67
- path.join(process.cwd(), config_filename),
68
- path.join(process.cwd(), '..', config_filename),
69
- path.join(process.cwd(), '..', '..', config_filename),
70
- ];
71
- for (const config_path of search_paths) {
72
- try {
73
- if (fs.existsSync(config_path)) {
74
- return config_path;
75
- }
76
- }
77
- catch {
78
- // Continue to next path
79
- }
80
- }
81
- return null;
82
- }
83
- /**
84
- * Read sqlite_path from hazo_llm_api_config.ini file
85
- * Searches in current directory and parent directories
86
- */
87
- function get_sqlite_path_from_config() {
88
- const default_path = 'prompt_library.sqlite';
89
- const config_path = find_config_file();
90
- if (config_path) {
91
- try {
92
- const config_content = fs.readFileSync(config_path, 'utf-8');
93
- const config = ini.parse(config_content);
94
- const sqlite_path = config.llm?.sqlite_path;
95
- if (sqlite_path) {
96
- default_logger.debug('Found sqlite_path in config', {
97
- file: 'index.ts',
98
- line: 137,
99
- data: { config_path, sqlite_path },
100
- });
101
- return sqlite_path;
102
- }
103
- }
104
- catch {
105
- // Use default
106
- }
107
- }
108
- default_logger.debug('Using default sqlite_path', {
109
- file: 'index.ts',
110
- line: 150,
111
- data: { default_path },
112
- });
113
- return default_path;
114
- }
115
- /**
116
- * Parse a generation config section from the ini file
117
- * Only includes parameters that are explicitly set (not commented out)
118
- * @param section - The parsed ini section object
119
- * @returns GeminiGenerationConfig or undefined if no params set
120
- */
121
- function parse_generation_config(section) {
122
- if (!section) {
123
- return undefined;
124
- }
125
- const config = {};
126
- let has_params = false;
127
- // Parse temperature (number)
128
- if (section.temperature !== undefined) {
129
- const temp = parseFloat(section.temperature);
130
- if (!isNaN(temp)) {
131
- config.temperature = temp;
132
- has_params = true;
133
- }
134
- }
135
- // Parse maxOutputTokens / max_output_tokens (number)
136
- const max_tokens = section.maxOutputTokens || section.max_output_tokens;
137
- if (max_tokens !== undefined) {
138
- const tokens = parseInt(max_tokens, 10);
139
- if (!isNaN(tokens)) {
140
- config.max_output_tokens = tokens;
141
- has_params = true;
142
- }
143
- }
144
- // Parse topP / top_p (number)
145
- const top_p = section.topP || section.top_p;
146
- if (top_p !== undefined) {
147
- const p = parseFloat(top_p);
148
- if (!isNaN(p)) {
149
- config.top_p = p;
150
- has_params = true;
151
- }
152
- }
153
- // Parse topK / top_k (number)
154
- const top_k = section.topK || section.top_k;
155
- if (top_k !== undefined) {
156
- const k = parseInt(top_k, 10);
157
- if (!isNaN(k)) {
158
- config.top_k = k;
159
- has_params = true;
160
- }
161
- }
162
- // Parse candidateCount / candidate_count (number)
163
- const candidate_count = section.candidateCount || section.candidate_count;
164
- if (candidate_count !== undefined) {
165
- const count = parseInt(candidate_count, 10);
166
- if (!isNaN(count)) {
167
- config.candidate_count = count;
168
- has_params = true;
169
- }
170
- }
171
- // Parse stopSequences / stop_sequences (JSON array string)
172
- const stop_sequences = section.stopSequences || section.stop_sequences;
173
- if (stop_sequences !== undefined) {
174
- try {
175
- const sequences = JSON.parse(stop_sequences);
176
- if (Array.isArray(sequences) && sequences.length > 0) {
177
- config.stop_sequences = sequences;
178
- has_params = true;
179
- }
180
- }
181
- catch {
182
- // Invalid JSON, skip
183
- }
184
- }
185
- // Parse responseMimeType / response_mime_type (string)
186
- const response_mime_type = section.responseMimeType || section.response_mime_type;
187
- if (response_mime_type !== undefined) {
188
- config.response_mime_type = response_mime_type;
189
- has_params = true;
190
- }
191
- return has_params ? config : undefined;
192
- }
193
- /**
194
- * Parse generation config from a section with optional prefix
195
- * Supports prefixed configs like "text_temperature" or "image_temperature"
196
- * @param section - The parsed ini section object
197
- * @param prefix - Optional prefix to filter keys (e.g., "text_" or "image_")
198
- * @returns GeminiGenerationConfig or undefined if no params set
199
- */
200
- function parse_prefixed_generation_config(section, prefix) {
201
- if (!section) {
202
- return undefined;
203
- }
204
- const config = {};
205
- let has_params = false;
206
- // Helper to get value with or without prefix
207
- const get_value = (key) => {
208
- if (prefix) {
209
- return section[`${prefix}${key}`];
210
- }
211
- return section[key];
212
- };
213
- // Parse temperature (number)
214
- const temp = get_value('temperature');
215
- if (temp !== undefined) {
216
- const temp_val = parseFloat(temp);
217
- if (!isNaN(temp_val)) {
218
- config.temperature = temp_val;
219
- has_params = true;
220
- }
221
- }
222
- // Parse maxOutputTokens (number)
223
- const max_tokens = get_value('maxOutputTokens') || get_value('max_output_tokens');
224
- if (max_tokens !== undefined) {
225
- const tokens = parseInt(max_tokens, 10);
226
- if (!isNaN(tokens)) {
227
- config.max_output_tokens = tokens;
228
- has_params = true;
229
- }
230
- }
231
- // Parse topP (number)
232
- const top_p = get_value('topP') || get_value('top_p');
233
- if (top_p !== undefined) {
234
- const p = parseFloat(top_p);
235
- if (!isNaN(p)) {
236
- config.top_p = p;
237
- has_params = true;
238
- }
239
- }
240
- // Parse topK (number)
241
- const top_k = get_value('topK') || get_value('top_k');
242
- if (top_k !== undefined) {
243
- const k = parseInt(top_k, 10);
244
- if (!isNaN(k)) {
245
- config.top_k = k;
246
- has_params = true;
247
- }
248
- }
249
- // Parse candidateCount (number)
250
- const candidate_count = get_value('candidateCount') || get_value('candidate_count');
251
- if (candidate_count !== undefined) {
252
- const count = parseInt(candidate_count, 10);
253
- if (!isNaN(count)) {
254
- config.candidate_count = count;
255
- has_params = true;
256
- }
257
- }
258
- // Parse stopSequences (JSON array string)
259
- const stop_sequences = get_value('stopSequences') || get_value('stop_sequences');
260
- if (stop_sequences !== undefined) {
261
- try {
262
- const sequences = JSON.parse(stop_sequences);
263
- if (Array.isArray(sequences) && sequences.length > 0) {
264
- config.stop_sequences = sequences;
265
- has_params = true;
266
- }
267
- }
268
- catch {
269
- // Invalid JSON, skip
270
- }
271
- }
272
- // Parse responseMimeType (string)
273
- const response_mime_type = get_value('responseMimeType') || get_value('response_mime_type');
274
- if (response_mime_type !== undefined) {
275
- config.response_mime_type = response_mime_type;
276
- has_params = true;
277
- }
278
- return has_params ? config : undefined;
279
- }
280
- /**
281
- * Parse capabilities from config value (JSON array or comma-separated)
282
- * @param value - Capabilities value from config
283
- * @returns Array of ServiceType or empty array
284
- */
285
- function parse_capabilities(value) {
286
- if (!value) {
287
- return [];
288
- }
289
- try {
290
- // Try parsing as JSON array first
291
- const parsed = JSON.parse(value);
292
- if (Array.isArray(parsed)) {
293
- return parsed.filter(cap => Object.values(SERVICE_TYPES).includes(cap));
294
- }
295
- }
296
- catch {
297
- // Not JSON, try comma-separated
298
- const caps = value.split(',').map(c => c.trim()).filter(Boolean);
299
- return caps.filter(cap => Object.values(SERVICE_TYPES).includes(cap));
300
- }
301
- return [];
302
- }
303
- /**
304
- * Parse enabled_llms from config (JSON array or comma-separated)
305
- * @param value - Enabled LLMs value from config
306
- * @returns Array of LLM names
307
- */
308
- function parse_enabled_llms(value) {
309
- if (!value) {
310
- return ['gemini']; // Default to gemini
311
- }
312
- try {
313
- // Try parsing as JSON array first
314
- const parsed = JSON.parse(value);
315
- if (Array.isArray(parsed)) {
316
- return parsed.filter((name) => typeof name === 'string' && name.length > 0);
317
- }
318
- }
319
- catch {
320
- // Not JSON, try comma-separated
321
- return value.split(',').map(name => name.trim()).filter(Boolean);
322
- }
323
- return [];
324
- }
325
- /**
326
- * Load API key from environment variable
327
- * @param provider_name - Provider name (e.g., "gemini")
328
- * @returns API key or undefined if not found
329
- */
330
- function load_api_key_from_env(provider_name) {
331
- // Try provider-specific env var: GEMINI_API_KEY, OPENAI_API_KEY, etc.
332
- const env_var_name = `${provider_name.toUpperCase()}_API_KEY`;
333
- return process.env[env_var_name];
334
- }
335
- /**
336
- * Read LLM global config from [llm] section
337
- * @returns Object with enabled_llms and primary_llm
338
- */
339
- function get_llm_global_config() {
340
- const config_path = find_config_file();
341
- const default_enabled = ['gemini'];
342
- const default_primary = 'gemini';
343
- const default_sqlite = 'prompt_library.sqlite';
344
- if (!config_path) {
345
- return {
346
- enabled_llms: default_enabled,
347
- primary_llm: default_primary,
348
- sqlite_path: default_sqlite,
349
- };
350
- }
351
- try {
352
- const config_content = fs.readFileSync(config_path, 'utf-8');
353
- const config = ini.parse(config_content);
354
- const llm_section = config.llm || {};
355
- const enabled_llms = parse_enabled_llms(llm_section.enabled_llms);
356
- const primary_llm = llm_section.primary_llm || default_primary;
357
- const sqlite_path = llm_section.sqlite_path || default_sqlite;
358
- return {
359
- enabled_llms: enabled_llms.length > 0 ? enabled_llms : default_enabled,
360
- primary_llm,
361
- sqlite_path,
362
- };
363
- }
364
- catch {
365
- return {
366
- enabled_llms: default_enabled,
367
- primary_llm: default_primary,
368
- sqlite_path: default_sqlite,
369
- };
370
- }
371
- }
372
- /**
373
- * Load and initialize Gemini provider from config
374
- * @param logger - Logger instance
375
- * @returns GeminiProvider instance or null if config invalid
376
- */
377
- function load_gemini_provider_from_config(logger) {
378
- const config_path = find_config_file();
379
- if (!config_path) {
380
- logger.warn('Config file not found, cannot load Gemini provider', {
381
- file: 'index.ts',
382
- line: 340,
383
- });
384
- return null;
385
- }
386
- try {
387
- const config_content = fs.readFileSync(config_path, 'utf-8');
388
- const config = ini.parse(config_content);
389
- const gemini_section = config.llm_gemini || {};
390
- // Load API key from environment
391
- const api_key = load_api_key_from_env('gemini');
392
- if (!api_key) {
393
- logger.error('GEMINI_API_KEY not found in environment variables', {
394
- file: 'index.ts',
395
- line: 352,
396
- data: { config_path },
397
- });
398
- return null;
399
- }
400
- // Parse capabilities
401
- const capabilities = parse_capabilities(gemini_section.capabilities);
402
- // Parse generation configs with prefixes
403
- const text_config = parse_prefixed_generation_config(gemini_section, 'text_');
404
- const image_config = parse_prefixed_generation_config(gemini_section, 'image_');
405
- const provider_config = {
406
- api_key,
407
- api_url: gemini_section.api_url,
408
- api_url_image: gemini_section.api_url_image,
409
- model_text_text: gemini_section.model_text_text,
410
- model_image_text: gemini_section.model_image_text,
411
- model_text_image: gemini_section.model_text_image,
412
- model_image_image: gemini_section.model_image_image,
413
- text_config,
414
- image_config,
415
- capabilities: capabilities.length > 0 ? capabilities : undefined,
416
- logger,
417
- };
418
- return new GeminiProvider(provider_config);
419
- }
420
- catch (error) {
421
- const error_message = error instanceof Error ? error.message : String(error);
422
- logger.error('Failed to load Gemini provider from config', {
423
- file: 'index.ts',
424
- line: 378,
425
- data: { error: error_message, config_path },
426
- });
427
- return null;
428
- }
429
- }
430
- /**
431
- * Parse Qwen generation config from a section with optional prefix
432
- * Supports prefixed configs like "text_temperature" or "image_temperature"
433
- * @param section - The parsed ini section object
434
- * @param prefix - Optional prefix to filter keys (e.g., "text_" or "image_")
435
- * @returns QwenGenerationConfig or undefined if no params set
436
- */
437
- function parse_prefixed_qwen_generation_config(section, prefix) {
438
- if (!section) {
439
- return undefined;
440
- }
441
- const config = {};
442
- let has_params = false;
443
- // Helper to get value with or without prefix
444
- const get_value = (key) => {
445
- if (prefix) {
446
- return section[`${prefix}${key}`];
447
- }
448
- return section[key];
449
- };
450
- // Parse temperature (number)
451
- const temp = get_value('temperature');
452
- if (temp !== undefined) {
453
- const temp_val = parseFloat(temp);
454
- if (!isNaN(temp_val)) {
455
- config.temperature = temp_val;
456
- has_params = true;
457
- }
458
- }
459
- // Parse max_tokens (number)
460
- const max_tokens = get_value('max_tokens');
461
- if (max_tokens !== undefined) {
462
- const tokens = parseInt(max_tokens, 10);
463
- if (!isNaN(tokens)) {
464
- config.max_tokens = tokens;
465
- has_params = true;
466
- }
467
- }
468
- // Parse top_p (number)
469
- const top_p = get_value('top_p');
470
- if (top_p !== undefined) {
471
- const p = parseFloat(top_p);
472
- if (!isNaN(p)) {
473
- config.top_p = p;
474
- has_params = true;
475
- }
476
- }
477
- // Parse top_k (number)
478
- const top_k = get_value('top_k');
479
- if (top_k !== undefined) {
480
- const k = parseInt(top_k, 10);
481
- if (!isNaN(k)) {
482
- config.top_k = k;
483
- has_params = true;
484
- }
485
- }
486
- // Parse n (number)
487
- const n = get_value('n');
488
- if (n !== undefined) {
489
- const n_val = parseInt(n, 10);
490
- if (!isNaN(n_val)) {
491
- config.n = n_val;
492
- has_params = true;
493
- }
494
- }
495
- // Parse stop (JSON array string)
496
- const stop = get_value('stop');
497
- if (stop !== undefined) {
498
- try {
499
- const sequences = JSON.parse(stop);
500
- if (Array.isArray(sequences) && sequences.length > 0) {
501
- config.stop = sequences;
502
- has_params = true;
503
- }
504
- }
505
- catch {
506
- // Invalid JSON, skip
507
- }
508
- }
509
- // Parse presence_penalty (number)
510
- const presence_penalty = get_value('presence_penalty');
511
- if (presence_penalty !== undefined) {
512
- const penalty = parseFloat(presence_penalty);
513
- if (!isNaN(penalty)) {
514
- config.presence_penalty = penalty;
515
- has_params = true;
516
- }
517
- }
518
- // Parse frequency_penalty (number)
519
- const frequency_penalty = get_value('frequency_penalty');
520
- if (frequency_penalty !== undefined) {
521
- const penalty = parseFloat(frequency_penalty);
522
- if (!isNaN(penalty)) {
523
- config.frequency_penalty = penalty;
524
- has_params = true;
525
- }
526
- }
527
- return has_params ? config : undefined;
528
- }
529
- /**
530
- * Load and initialize Qwen provider from config
531
- * @param logger - Logger instance
532
- * @returns QwenProvider instance or null if config invalid
533
- */
534
- function load_qwen_provider_from_config(logger) {
535
- const config_path = find_config_file();
536
- if (!config_path) {
537
- logger.warn('Config file not found, cannot load Qwen provider', {
538
- file: 'index.ts',
539
- line: 500,
540
- });
541
- return null;
542
- }
543
- try {
544
- const config_content = fs.readFileSync(config_path, 'utf-8');
545
- const config = ini.parse(config_content);
546
- const qwen_section = config.llm_qwen || {};
547
- // Load API key from environment
548
- const api_key = load_api_key_from_env('qwen');
549
- if (!api_key) {
550
- logger.error('QWEN_API_KEY not found in environment variables', {
551
- file: 'index.ts',
552
- line: 512,
553
- data: { config_path },
554
- });
555
- return null;
556
- }
557
- // Parse capabilities
558
- const capabilities = parse_capabilities(qwen_section.capabilities);
559
- // Parse generation configs with prefixes
560
- const text_config = parse_prefixed_qwen_generation_config(qwen_section, 'text_');
561
- const image_config = parse_prefixed_qwen_generation_config(qwen_section, 'image_');
562
- const provider_config = {
563
- api_key,
564
- api_url: qwen_section.api_url,
565
- model_text_text: qwen_section.model_text_text,
566
- model_image_text: qwen_section.model_image_text,
567
- model_text_image: qwen_section.model_text_image,
568
- model_image_image: qwen_section.model_image_image,
569
- api_url_text_text: qwen_section.api_url_text_text,
570
- api_url_image_text: qwen_section.api_url_image_text,
571
- api_url_text_image: qwen_section.api_url_text_image,
572
- api_url_image_image: qwen_section.api_url_image_image,
573
- system_instruction: qwen_section.system_instruction,
574
- text_config,
575
- image_config,
576
- capabilities: capabilities.length > 0 ? capabilities : undefined,
577
- logger,
578
- };
579
- return new QwenProvider(provider_config);
580
- }
581
- catch (error) {
582
- const error_message = error instanceof Error ? error.message : String(error);
583
- logger.error('Failed to load Qwen provider from config', {
584
- file: 'index.ts',
585
- line: 543,
586
- data: { error: error_message, config_path },
587
- });
588
- return null;
589
- }
590
- }
591
- /**
592
- * Load and register all enabled providers from config file
593
- * @param logger - Logger instance
594
- */
595
- function load_and_register_providers(logger) {
596
- const global_config = get_llm_global_config();
597
- // Set enabled LLMs and primary LLM in registry
598
- set_enabled_llms(global_config.enabled_llms);
599
- set_primary_llm(global_config.primary_llm);
600
- logger.info('Loading LLM providers from config', {
601
- file: 'index.ts',
602
- line: 395,
603
- data: {
604
- enabled_llms: global_config.enabled_llms,
605
- primary_llm: global_config.primary_llm,
606
- },
607
- });
608
- // Load each enabled provider
609
- for (const llm_name of global_config.enabled_llms) {
610
- if (llm_name.toLowerCase() === 'gemini') {
611
- const provider = load_gemini_provider_from_config(logger);
612
- if (provider) {
613
- register_provider(provider);
614
- logger.info('Registered Gemini provider', {
615
- file: 'index.ts',
616
- line: 636,
617
- data: {
618
- capabilities: Array.from(provider.get_capabilities()),
619
- },
620
- });
621
- }
622
- else {
623
- logger.warn('Gemini provider is enabled in config but failed to load. Check GEMINI_API_KEY in environment variables.', {
624
- file: 'index.ts',
625
- line: 716,
626
- data: { llm_name: llm_name.toLowerCase() },
627
- });
628
- }
629
- }
630
- else if (llm_name.toLowerCase() === 'qwen') {
631
- const provider = load_qwen_provider_from_config(logger);
632
- if (provider) {
633
- register_provider(provider);
634
- logger.info('Registered Qwen provider', {
635
- file: 'index.ts',
636
- line: 646,
637
- data: {
638
- capabilities: Array.from(provider.get_capabilities()),
639
- },
640
- });
641
- }
642
- else {
643
- logger.warn('Qwen provider is enabled in config but failed to load. Check QWEN_API_KEY in environment variables.', {
644
- file: 'index.ts',
645
- line: 728,
646
- data: { llm_name: llm_name.toLowerCase() },
647
- });
648
- }
649
- }
650
- // Future: Add other providers here (OpenAI, Anthropic, etc.)
651
- }
652
- }
653
- // =============================================================================
654
- // Auto-initialization on Import
655
- // =============================================================================
656
- /**
657
- * Auto-initialize database when module is imported
658
- * Uses config file defaults, does not require API key
659
- */
660
- async function auto_initialize_database() {
661
- if (db_auto_initialized) {
662
- return;
663
- }
664
- const file_name = 'index.ts (llm_api)';
665
- try {
666
- const sqlite_path = get_sqlite_path_from_config();
667
- default_logger.info('Auto-initializing database on module import', {
668
- file: file_name,
669
- line: 110,
670
- data: { sqlite_path },
671
- });
672
- await initialize_database(sqlite_path, default_logger);
673
- db_auto_initialized = true;
674
- default_logger.info('Database auto-initialized successfully', {
675
- file: file_name,
676
- line: 118,
677
- data: { sqlite_path },
678
- });
679
- }
680
- catch (error) {
681
- const error_message = error instanceof Error ? error.message : String(error);
682
- default_logger.error('Failed to auto-initialize database', {
683
- file: file_name,
684
- line: 124,
685
- data: { error: error_message },
686
- });
687
- // Don't throw - allow manual initialization later
688
- }
689
- }
690
- // Trigger auto-initialization when module is imported
691
- // Using void to handle the promise without blocking
692
- void auto_initialize_database();
693
- // =============================================================================
694
- // Initialization Function
695
- // =============================================================================
696
- /**
697
- * Initialize the LLM API with the given configuration
698
- * Creates/connects to the database and prepares the client for use
699
- *
700
- * @param config - Configuration options for the LLM API
701
- * @returns Initialized LLM API client
702
- */
703
- export async function initialize_llm_api(config) {
704
- const file_name = 'index.ts (llm_api)';
705
- const logger = config.logger;
706
- // Get global config from file
707
- const global_config = get_llm_global_config();
708
- // Use provided sqlite_path or fall back to config file value
709
- const sqlite_path = config.sqlite_path || global_config.sqlite_path;
710
- // Load and register providers from config file
711
- load_and_register_providers(logger);
712
- // Validate that primary_llm is enabled
713
- const primary_llm_name = get_primary_llm();
714
- if (!primary_llm_name) {
715
- const error_msg = 'No primary LLM configured. Set primary_llm in [llm] section of config file.';
716
- logger.error(error_msg, {
717
- file: file_name,
718
- line: 615,
719
- });
720
- throw new Error(error_msg);
721
- }
722
- logger.info('Initializing LLM API', {
723
- file: file_name,
724
- line: 620,
725
- data: {
726
- sqlite_path,
727
- enabled_llms: global_config.enabled_llms,
728
- primary_llm: primary_llm_name,
729
- },
730
- });
731
- // Set final config for backward compatibility (simplified)
732
- const final_config = {
733
- logger: config.logger,
734
- sqlite_path,
735
- // Legacy fields kept for backward compatibility but not used by providers
736
- api_url: config.api_url,
737
- api_url_image: config.api_url_image,
738
- api_key: config.api_key,
739
- llm_model: primary_llm_name, // Use primary_llm as default
740
- };
741
- // Initialize the database (async)
742
- try {
743
- await initialize_database(sqlite_path, logger);
744
- initialized = true;
745
- current_config = final_config;
746
- logger.info('LLM API initialized successfully', {
747
- file: file_name,
748
- line: 645,
749
- data: {
750
- primary_llm: primary_llm_name,
751
- registered_providers: get_registered_providers(),
752
- },
753
- });
754
- }
755
- catch (error) {
756
- const error_message = error instanceof Error ? error.message : String(error);
757
- logger.error('Failed to initialize LLM API', {
758
- file: file_name,
759
- line: 653,
760
- data: { error: error_message },
761
- });
762
- throw error;
763
- }
764
- // Create and return the client instance
765
- const client = {
766
- config: final_config,
767
- db_initialized: initialized,
768
- hazo_llm_text_text: async (params, llm) => {
769
- return hazo_llm_text_text(params, llm);
770
- },
771
- hazo_llm_image_text: async (params, llm) => {
772
- return hazo_llm_image_text(params, llm);
773
- },
774
- hazo_llm_text_image: async (params, llm) => {
775
- return hazo_llm_text_image(params, llm);
776
- },
777
- hazo_llm_image_image: async (params, llm) => {
778
- return hazo_llm_image_image(params, llm);
779
- },
780
- hazo_llm_text_image_text: async (params, llm) => {
781
- return hazo_llm_text_image_text(params, llm);
782
- },
783
- hazo_llm_image_image_text: async (params, llm) => {
784
- return hazo_llm_image_image_text(params, llm);
785
- },
786
- };
787
- return client;
788
- }
789
- // =============================================================================
790
- // Module Level Functions
791
- // =============================================================================
792
- /**
793
- * Helper to check full LLM API initialization (required for LLM calls)
794
- */
795
- function check_initialized() {
796
- if (!initialized || !current_config) {
797
- throw new Error('LLM API not initialized. Call initialize_llm_api first.');
798
- }
799
- return current_config;
800
- }
801
- /**
802
- * Check if database has been initialized (either auto or manual)
803
- * @returns true if database is ready for use
804
- */
805
- export function is_database_ready() {
806
- return db_auto_initialized || initialized;
807
- }
808
- /**
809
- * Wait for auto-initialization to complete
810
- * Useful if you need to ensure database is ready before operations
811
- */
812
- export async function ensure_database_ready() {
813
- if (db_auto_initialized || initialized) {
814
- return true;
815
- }
816
- // If not yet initialized, trigger it now
817
- await auto_initialize_database();
818
- return db_auto_initialized;
819
- }
820
- /**
821
- * Text input → Text output
822
- * Standard text generation using LLM
823
- *
824
- * @param params - Text input parameters
825
- * @param llm - Optional LLM provider name (uses primary LLM if not specified)
826
- * @returns LLM response with generated text
827
- */
828
- export async function hazo_llm_text_text(params, llm) {
829
- try {
830
- const config = check_initialized();
831
- const db = get_database();
832
- return hazo_llm_text_text_internal(params, db, config, llm);
833
- }
834
- catch (error) {
835
- return { success: false, error: error instanceof Error ? error.message : String(error) };
836
- }
837
- }
838
- /**
839
- * Image input → Text output
840
- * Analyze an image and get text description
841
- *
842
- * @param params - Image input parameters
843
- * @param llm - Optional LLM provider name (uses primary LLM if not specified)
844
- * @returns LLM response with text description
845
- */
846
- export async function hazo_llm_image_text(params, llm) {
847
- try {
848
- const config = check_initialized();
849
- const db = get_database();
850
- return hazo_llm_image_text_internal(params, db, config, llm);
851
- }
852
- catch (error) {
853
- return { success: false, error: error instanceof Error ? error.message : String(error) };
854
- }
855
- }
856
- /**
857
- * Text input → Image output
858
- * Generate an image from text description
859
- *
860
- * @param params - Text input parameters for image generation
861
- * @param llm - Optional LLM provider name (uses primary LLM if not specified)
862
- * @returns LLM response with generated image
863
- */
864
- export async function hazo_llm_text_image(params, llm) {
865
- try {
866
- const config = check_initialized();
867
- const db = get_database();
868
- return hazo_llm_text_image_internal(params, db, config, llm);
869
- }
870
- catch (error) {
871
- return { success: false, error: error instanceof Error ? error.message : String(error) };
872
- }
873
- }
874
- /**
875
- * Image input → Image output
876
- * Transform/edit an image based on instructions
877
- *
878
- * @param params - Image input parameters with transformation instructions
879
- * @param llm - Optional LLM provider name (uses primary LLM if not specified)
880
- * @returns LLM response with transformed image
881
- */
882
- export async function hazo_llm_image_image(params, llm) {
883
- try {
884
- const config = check_initialized();
885
- const db = get_database();
886
- return hazo_llm_image_image_internal(params, db, config, llm);
887
- }
888
- catch (error) {
889
- return { success: false, error: error instanceof Error ? error.message : String(error) };
890
- }
891
- }
892
- /**
893
- * Text → Image → Text (Chained)
894
- * Generate an image from prompt_image, then analyze it with prompt_text
895
- *
896
- * @param params - Parameters with two prompts: one for image gen, one for analysis
897
- * @param llm - Optional LLM provider name (uses primary LLM if not specified)
898
- * @returns LLM response with generated image and analysis text
899
- */
900
- export async function hazo_llm_text_image_text(params, llm) {
901
- try {
902
- const config = check_initialized();
903
- const db = get_database();
904
- return hazo_llm_text_image_text_internal(params, db, config, llm);
905
- }
906
- catch (error) {
907
- return { success: false, error: error instanceof Error ? error.message : String(error) };
908
- }
909
- }
910
- /**
911
- * Images → Image → Text (Chained)
912
- * Chain multiple image transformations, then describe the final result
913
- *
914
- * @param params - Parameters with images, prompts, and description prompt
915
- * @param llm - Optional LLM provider name (uses primary LLM if not specified)
916
- * @returns LLM response with final image and description text
917
- */
918
- export async function hazo_llm_image_image_text(params, llm) {
919
- try {
920
- const config = check_initialized();
921
- const db = get_database();
922
- return hazo_llm_image_image_text_internal(params, db, config, llm);
923
- }
924
- catch (error) {
925
- return { success: false, error: error instanceof Error ? error.message : String(error) };
926
- }
927
- }
928
- // =============================================================================
929
- // Utility Functions
930
- // =============================================================================
931
- /**
932
- * Check if the LLM API has been initialized
933
- * @returns true if initialized
934
- */
935
- export function is_initialized() {
936
- return initialized;
937
- }
938
- /**
939
- * Get the current configuration (without sensitive data)
940
- * @returns Current configuration or null if not initialized
941
- */
942
- export function get_current_config() {
943
- if (!current_config) {
944
- return null;
945
- }
946
- return {
947
- llm_model: current_config.llm_model,
948
- sqlite_path: current_config.sqlite_path,
949
- api_url: current_config.api_url,
950
- };
951
- }
952
- //# sourceMappingURL=index.js.map