genai-lite 0.6.1 → 0.7.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.
@@ -9,6 +9,8 @@ exports.OpenAIClientAdapter = void 0;
9
9
  const openai_1 = __importDefault(require("openai"));
10
10
  const types_1 = require("./types");
11
11
  const errorUtils_1 = require("../../shared/adapters/errorUtils");
12
+ const defaultLogger_1 = require("../../logging/defaultLogger");
13
+ const logger = (0, defaultLogger_1.createDefaultLogger)();
12
14
  /**
13
15
  * Client adapter for OpenAI API integration
14
16
  *
@@ -76,7 +78,7 @@ class OpenAIClientAdapter {
76
78
  completionParams.reasoning_effort = 'medium';
77
79
  }
78
80
  }
79
- console.log(`OpenAI API parameters:`, {
81
+ logger.debug(`OpenAI API parameters:`, {
80
82
  model: completionParams.model,
81
83
  temperature: completionParams.temperature,
82
84
  max_completion_tokens: completionParams.max_completion_tokens,
@@ -86,12 +88,12 @@ class OpenAIClientAdapter {
86
88
  presence_penalty: completionParams.presence_penalty,
87
89
  hasUser: !!completionParams.user,
88
90
  });
89
- console.log(`Making OpenAI API call for model: ${request.modelId}`);
91
+ logger.info(`Making OpenAI API call for model: ${request.modelId}`);
90
92
  // Make the API call
91
93
  const completion = await openai.chat.completions.create(completionParams);
92
94
  // Type guard to ensure we have a non-streaming response
93
95
  if ('id' in completion && 'choices' in completion) {
94
- console.log(`OpenAI API call successful, response ID: ${completion.id}`);
96
+ logger.info(`OpenAI API call successful, response ID: ${completion.id}`);
95
97
  // Convert to standardized response format
96
98
  return this.createSuccessResponse(completion, request);
97
99
  }
@@ -100,7 +102,7 @@ class OpenAIClientAdapter {
100
102
  }
101
103
  }
102
104
  catch (error) {
103
- console.error("OpenAI API error:", error);
105
+ logger.error("OpenAI API error:", error);
104
106
  return this.createErrorResponse(error, request);
105
107
  }
106
108
  }
@@ -16,6 +16,8 @@ const OpenAIClientAdapter_1 = require("./clients/OpenAIClientAdapter");
16
16
  const AnthropicClientAdapter_1 = require("./clients/AnthropicClientAdapter");
17
17
  const GeminiClientAdapter_1 = require("./clients/GeminiClientAdapter");
18
18
  const LlamaCppClientAdapter_1 = require("./clients/LlamaCppClientAdapter");
19
+ const defaultLogger_1 = require("../logging/defaultLogger");
20
+ const logger = (0, defaultLogger_1.createDefaultLogger)();
19
21
  // Placeholder for future imports:
20
22
  // import { MistralClientAdapter } from './clients/MistralClientAdapter';
21
23
  /**
@@ -271,7 +273,7 @@ function detectGgufCapabilities(ggufFilename) {
271
273
  // First match wins (array is pre-ordered from specific to generic)
272
274
  for (const model of exports.KNOWN_GGUF_MODELS) {
273
275
  if (lowerFilename.includes(model.pattern.toLowerCase())) {
274
- console.log(`Detected GGUF model: ${model.name} (pattern: ${model.pattern})`);
276
+ logger.debug(`Detected GGUF model: ${model.name} (pattern: ${model.pattern})`);
275
277
  return model.capabilities;
276
278
  }
277
279
  }
@@ -588,32 +590,6 @@ exports.SUPPORTED_MODELS = [
588
590
  outputType: 'summary',
589
591
  },
590
592
  },
591
- {
592
- id: "gemini-2.0-flash",
593
- name: "Gemini 2.0 Flash",
594
- providerId: "gemini",
595
- contextWindow: 1048576,
596
- inputPrice: 0.1,
597
- outputPrice: 0.4,
598
- description: "High-performance model with multimodal capabilities",
599
- maxTokens: 8192,
600
- supportsImages: true,
601
- supportsPromptCache: true,
602
- cacheReadsPrice: 0.025,
603
- cacheWritesPrice: 1.0,
604
- },
605
- {
606
- id: "gemini-2.0-flash-lite",
607
- name: "Gemini 2.0 Flash Lite",
608
- providerId: "gemini",
609
- contextWindow: 1048576,
610
- inputPrice: 0.075,
611
- outputPrice: 0.3,
612
- description: "Lightweight version of Gemini 2.0 Flash",
613
- maxTokens: 8192,
614
- supportsImages: true,
615
- supportsPromptCache: false,
616
- },
617
593
  // Google Gemma 3 Models (Open weights, free via Gemini API)
618
594
  {
619
595
  id: "gemma-3-27b-it",
@@ -1,6 +1,7 @@
1
1
  import type { LLMFailureResponse, LLMSettings, ModelInfo, ApiProviderId } from "../types";
2
2
  import type { ILLMClientAdapter } from "../clients/types";
3
3
  import type { ModelPreset } from "../../types/presets";
4
+ import type { Logger } from "../../logging/types";
4
5
  import { PresetManager } from "../../shared/services/PresetManager";
5
6
  import { AdapterRegistry } from "../../shared/services/AdapterRegistry";
6
7
  /**
@@ -28,7 +29,8 @@ export interface ModelResolution {
28
29
  export declare class ModelResolver {
29
30
  private presetManager;
30
31
  private adapterRegistry;
31
- constructor(presetManager: PresetManager<ModelPreset>, adapterRegistry: AdapterRegistry<ILLMClientAdapter, ApiProviderId>);
32
+ private logger;
33
+ constructor(presetManager: PresetManager<ModelPreset>, adapterRegistry: AdapterRegistry<ILLMClientAdapter, ApiProviderId>, logger?: Logger);
32
34
  /**
33
35
  * Resolves model information from either a preset ID or provider/model IDs
34
36
  *
@@ -1,14 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ModelResolver = void 0;
4
+ const defaultLogger_1 = require("../../logging/defaultLogger");
4
5
  const config_1 = require("../config");
5
6
  /**
6
7
  * Resolves model information from presets or direct provider/model IDs
7
8
  */
8
9
  class ModelResolver {
9
- constructor(presetManager, adapterRegistry) {
10
+ constructor(presetManager, adapterRegistry, logger) {
10
11
  this.presetManager = presetManager;
11
12
  this.adapterRegistry = adapterRegistry;
13
+ this.logger = logger ?? (0, defaultLogger_1.createDefaultLogger)();
12
14
  }
13
15
  /**
14
16
  * Resolves model information from either a preset ID or provider/model IDs
@@ -107,7 +109,7 @@ class ModelResolver {
107
109
  }
108
110
  }
109
111
  catch (error) {
110
- console.warn('Failed to detect GGUF model capabilities:', error);
112
+ this.logger.warn('Failed to detect GGUF model capabilities:', error);
111
113
  // Continue with fallback
112
114
  }
113
115
  }
@@ -117,7 +119,7 @@ class ModelResolver {
117
119
  }
118
120
  else {
119
121
  // Strict provider - warn but allow
120
- console.warn(`⚠️ Unknown model "${options.modelId}" for provider "${options.providerId}". ` +
122
+ this.logger.warn(`Unknown model "${options.modelId}" for provider "${options.providerId}". ` +
121
123
  `Using default settings. This may fail at the provider API if the model doesn't exist.`);
122
124
  modelInfo = (0, config_1.createFallbackModelInfo)(options.modelId, options.providerId, detectedCapabilities);
123
125
  }
@@ -1,8 +1,11 @@
1
1
  import type { ApiProviderId, LLMSettings, ModelInfo, ProviderInfo } from "../types";
2
+ import type { Logger } from "../../logging/types";
2
3
  /**
3
4
  * Manages LLM settings including merging with defaults and filtering unsupported parameters
4
5
  */
5
6
  export declare class SettingsManager {
7
+ private logger;
8
+ constructor(logger?: Logger);
6
9
  /**
7
10
  * Merges request settings with model-specific and global defaults
8
11
  *
@@ -1,11 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SettingsManager = void 0;
4
+ const defaultLogger_1 = require("../../logging/defaultLogger");
4
5
  const config_1 = require("../config");
5
6
  /**
6
7
  * Manages LLM settings including merging with defaults and filtering unsupported parameters
7
8
  */
8
9
  class SettingsManager {
10
+ constructor(logger) {
11
+ this.logger = logger ?? (0, defaultLogger_1.createDefaultLogger)();
12
+ }
9
13
  /**
10
14
  * Merges request settings with model-specific and global defaults
11
15
  *
@@ -40,7 +44,7 @@ class SettingsManager {
40
44
  },
41
45
  };
42
46
  // Log the final settings for debugging
43
- console.log(`Merged settings for ${providerId}/${modelId}:`, {
47
+ this.logger.debug(`Merged settings for ${providerId}/${modelId}:`, {
44
48
  temperature: mergedSettings.temperature,
45
49
  maxTokens: mergedSettings.maxTokens,
46
50
  topP: mergedSettings.topP,
@@ -74,23 +78,23 @@ class SettingsManager {
74
78
  modelInfo.unsupportedParameters.forEach((param) => paramsToExclude.add(param));
75
79
  }
76
80
  if (paramsToExclude.size > 0) {
77
- console.log(`LLMService: Potential parameters to exclude for provider '${providerInfo.id}', model '${modelInfo.id}':`, Array.from(paramsToExclude));
81
+ this.logger.debug(`LLMService: Potential parameters to exclude for provider '${providerInfo.id}', model '${modelInfo.id}':`, Array.from(paramsToExclude));
78
82
  }
79
83
  paramsToExclude.forEach((param) => {
80
84
  // Check if the parameter key actually exists in filteredSettings before trying to delete
81
85
  if (param in filteredSettings) {
82
- console.log(`LLMService: Removing excluded parameter '${String(param)}' for provider '${providerInfo.id}', model '${modelInfo.id}'. Value was:`, filteredSettings[param]);
86
+ this.logger.debug(`LLMService: Removing excluded parameter '${String(param)}' for provider '${providerInfo.id}', model '${modelInfo.id}'. Value was:`, filteredSettings[param]);
83
87
  delete filteredSettings[param]; // Cast to allow deletion
84
88
  }
85
89
  else {
86
90
  // This case should ideally not happen if settings truly is Required<LLMSettings>
87
- console.log(`LLMService: Parameter '${String(param)}' marked for exclusion was not found in settings for provider '${providerInfo.id}', model '${modelInfo.id}'.`);
91
+ this.logger.debug(`LLMService: Parameter '${String(param)}' marked for exclusion was not found in settings for provider '${providerInfo.id}', model '${modelInfo.id}'.`);
88
92
  }
89
93
  });
90
94
  // Handle reasoning settings for models that don't support it
91
95
  // This happens after validateReasoningSettings so we know it's safe to strip
92
96
  if (!modelInfo.reasoning?.supported && filteredSettings.reasoning) {
93
- console.log(`LLMService: Removing reasoning settings for non-reasoning model ${modelInfo.id}`);
97
+ this.logger.debug(`LLMService: Removing reasoning settings for non-reasoning model ${modelInfo.id}`);
94
98
  delete filteredSettings.reasoning;
95
99
  }
96
100
  return filteredSettings;
@@ -121,71 +125,71 @@ class SettingsManager {
121
125
  for (const [key, value] of Object.entries(settings)) {
122
126
  // Check if it's a known field
123
127
  if (!knownFields.includes(key)) {
124
- console.warn(`Unknown setting "${key}" in template metadata. Ignoring.`);
128
+ this.logger.warn(`Unknown setting "${key}" in template metadata. Ignoring.`);
125
129
  continue;
126
130
  }
127
131
  // Type-specific validation
128
132
  if (key === 'temperature') {
129
133
  if (typeof value !== 'number' || value < 0 || value > 2) {
130
- console.warn(`Invalid temperature value in template: ${value}. Must be a number between 0 and 2.`);
134
+ this.logger.warn(`Invalid temperature value in template: ${value}. Must be a number between 0 and 2.`);
131
135
  continue;
132
136
  }
133
137
  }
134
138
  if (key === 'maxTokens') {
135
139
  if (typeof value !== 'number' || value <= 0) {
136
- console.warn(`Invalid maxTokens value in template: ${value}. Must be a positive number.`);
140
+ this.logger.warn(`Invalid maxTokens value in template: ${value}. Must be a positive number.`);
137
141
  continue;
138
142
  }
139
143
  }
140
144
  if (key === 'topP') {
141
145
  if (typeof value !== 'number' || value < 0 || value > 1) {
142
- console.warn(`Invalid topP value in template: ${value}. Must be a number between 0 and 1.`);
146
+ this.logger.warn(`Invalid topP value in template: ${value}. Must be a number between 0 and 1.`);
143
147
  continue;
144
148
  }
145
149
  }
146
150
  if (key === 'stopSequences') {
147
151
  if (!Array.isArray(value) || !value.every(v => typeof v === 'string')) {
148
- console.warn(`Invalid stopSequences value in template. Must be an array of strings.`);
152
+ this.logger.warn(`Invalid stopSequences value in template. Must be an array of strings.`);
149
153
  continue;
150
154
  }
151
155
  }
152
156
  if ((key === 'frequencyPenalty' || key === 'presencePenalty')) {
153
157
  if (typeof value !== 'number' || value < -2 || value > 2) {
154
- console.warn(`Invalid ${key} value in template: ${value}. Must be a number between -2 and 2.`);
158
+ this.logger.warn(`Invalid ${key} value in template: ${value}. Must be a number between -2 and 2.`);
155
159
  continue;
156
160
  }
157
161
  }
158
162
  if (key === 'user' && typeof value !== 'string') {
159
- console.warn(`Invalid user value in template. Must be a string.`);
163
+ this.logger.warn(`Invalid user value in template. Must be a string.`);
160
164
  continue;
161
165
  }
162
166
  if (key === 'supportsSystemMessage' && typeof value !== 'boolean') {
163
- console.warn(`Invalid supportsSystemMessage value in template. Must be a boolean.`);
167
+ this.logger.warn(`Invalid supportsSystemMessage value in template. Must be a boolean.`);
164
168
  continue;
165
169
  }
166
170
  // Nested object validation
167
171
  if (key === 'reasoning' && typeof value === 'object' && value !== null) {
168
172
  const reasoningValidated = {};
169
173
  if ('enabled' in value && typeof value.enabled !== 'boolean') {
170
- console.warn(`Invalid reasoning.enabled value in template. Must be a boolean.`);
174
+ this.logger.warn(`Invalid reasoning.enabled value in template. Must be a boolean.`);
171
175
  }
172
176
  else if ('enabled' in value) {
173
177
  reasoningValidated.enabled = value.enabled;
174
178
  }
175
179
  if ('effort' in value && !['low', 'medium', 'high'].includes(value.effort)) {
176
- console.warn(`Invalid reasoning.effort value in template: ${value.effort}. Must be 'low', 'medium', or 'high'.`);
180
+ this.logger.warn(`Invalid reasoning.effort value in template: ${value.effort}. Must be 'low', 'medium', or 'high'.`);
177
181
  }
178
182
  else if ('effort' in value) {
179
183
  reasoningValidated.effort = value.effort;
180
184
  }
181
185
  if ('maxTokens' in value && (typeof value.maxTokens !== 'number' || value.maxTokens <= 0)) {
182
- console.warn(`Invalid reasoning.maxTokens value in template. Must be a positive number.`);
186
+ this.logger.warn(`Invalid reasoning.maxTokens value in template. Must be a positive number.`);
183
187
  }
184
188
  else if ('maxTokens' in value) {
185
189
  reasoningValidated.maxTokens = value.maxTokens;
186
190
  }
187
191
  if ('exclude' in value && typeof value.exclude !== 'boolean') {
188
- console.warn(`Invalid reasoning.exclude value in template. Must be a boolean.`);
192
+ this.logger.warn(`Invalid reasoning.exclude value in template. Must be a boolean.`);
189
193
  }
190
194
  else if ('exclude' in value) {
191
195
  reasoningValidated.exclude = value.exclude;
@@ -198,19 +202,19 @@ class SettingsManager {
198
202
  if (key === 'thinkingTagFallback' && typeof value === 'object' && value !== null) {
199
203
  const thinkingValidated = {};
200
204
  if ('enabled' in value && typeof value.enabled !== 'boolean') {
201
- console.warn(`Invalid thinkingTagFallback.enabled value in template. Must be a boolean.`);
205
+ this.logger.warn(`Invalid thinkingTagFallback.enabled value in template. Must be a boolean.`);
202
206
  }
203
207
  else if ('enabled' in value) {
204
208
  thinkingValidated.enabled = value.enabled;
205
209
  }
206
210
  if ('tagName' in value && typeof value.tagName !== 'string') {
207
- console.warn(`Invalid thinkingTagFallback.tagName value in template. Must be a string.`);
211
+ this.logger.warn(`Invalid thinkingTagFallback.tagName value in template. Must be a string.`);
208
212
  }
209
213
  else if ('tagName' in value) {
210
214
  thinkingValidated.tagName = value.tagName;
211
215
  }
212
216
  if ('enforce' in value && typeof value.enforce !== 'boolean') {
213
- console.warn(`Invalid thinkingTagFallback.enforce value in template. Must be a boolean.`);
217
+ this.logger.warn(`Invalid thinkingTagFallback.enforce value in template. Must be a boolean.`);
214
218
  }
215
219
  else if ('enforce' in value) {
216
220
  thinkingValidated.enforce = value.enforce;
@@ -0,0 +1,35 @@
1
+ import type { Logger, LogLevel } from './types';
2
+ /**
3
+ * The default log level, read once at module initialization.
4
+ * Can be overridden per-service via constructor options.
5
+ */
6
+ export declare const DEFAULT_LOG_LEVEL: LogLevel;
7
+ /**
8
+ * Creates a default console-based logger with level filtering.
9
+ *
10
+ * @param level - The minimum log level to output (defaults to env var or 'warn')
11
+ * @returns A Logger instance that filters messages below the specified level
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const logger = createDefaultLogger('debug');
16
+ * logger.debug('This will be shown');
17
+ * logger.info('This will be shown');
18
+ *
19
+ * const quietLogger = createDefaultLogger('error');
20
+ * quietLogger.debug('This will be suppressed');
21
+ * quietLogger.info('This will be suppressed');
22
+ * quietLogger.error('This will be shown');
23
+ * ```
24
+ */
25
+ export declare function createDefaultLogger(level?: LogLevel): Logger;
26
+ /**
27
+ * A silent logger that discards all output.
28
+ * Useful for testing or when logging should be completely disabled.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const service = new LLMService(apiKeyProvider, { logger: silentLogger });
33
+ * ```
34
+ */
35
+ export declare const silentLogger: Logger;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.silentLogger = exports.DEFAULT_LOG_LEVEL = void 0;
4
+ exports.createDefaultLogger = createDefaultLogger;
5
+ /**
6
+ * Numeric values for log levels (higher = more verbose)
7
+ */
8
+ const LOG_LEVEL_VALUES = {
9
+ silent: 0,
10
+ error: 1,
11
+ warn: 2,
12
+ info: 3,
13
+ debug: 4,
14
+ };
15
+ /**
16
+ * Valid log level strings for validation
17
+ */
18
+ const VALID_LOG_LEVELS = new Set(['silent', 'error', 'warn', 'info', 'debug']);
19
+ /**
20
+ * Reads the default log level from environment variable.
21
+ * Called once at module load time.
22
+ *
23
+ * @returns The log level from GENAI_LITE_LOG_LEVEL or 'warn' as default
24
+ */
25
+ function getDefaultLogLevelFromEnv() {
26
+ const envLevel = process.env.GENAI_LITE_LOG_LEVEL?.toLowerCase();
27
+ if (envLevel && VALID_LOG_LEVELS.has(envLevel)) {
28
+ return envLevel;
29
+ }
30
+ return 'warn'; // Sensible default: errors + warnings
31
+ }
32
+ /**
33
+ * The default log level, read once at module initialization.
34
+ * Can be overridden per-service via constructor options.
35
+ */
36
+ exports.DEFAULT_LOG_LEVEL = getDefaultLogLevelFromEnv();
37
+ /**
38
+ * Creates a default console-based logger with level filtering.
39
+ *
40
+ * @param level - The minimum log level to output (defaults to env var or 'warn')
41
+ * @returns A Logger instance that filters messages below the specified level
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const logger = createDefaultLogger('debug');
46
+ * logger.debug('This will be shown');
47
+ * logger.info('This will be shown');
48
+ *
49
+ * const quietLogger = createDefaultLogger('error');
50
+ * quietLogger.debug('This will be suppressed');
51
+ * quietLogger.info('This will be suppressed');
52
+ * quietLogger.error('This will be shown');
53
+ * ```
54
+ */
55
+ function createDefaultLogger(level = exports.DEFAULT_LOG_LEVEL) {
56
+ const threshold = LOG_LEVEL_VALUES[level];
57
+ return {
58
+ debug(message, ...args) {
59
+ if (threshold >= LOG_LEVEL_VALUES.debug) {
60
+ console.log(`[genai-lite:debug] ${message}`, ...args);
61
+ }
62
+ },
63
+ info(message, ...args) {
64
+ if (threshold >= LOG_LEVEL_VALUES.info) {
65
+ console.log(`[genai-lite:info] ${message}`, ...args);
66
+ }
67
+ },
68
+ warn(message, ...args) {
69
+ if (threshold >= LOG_LEVEL_VALUES.warn) {
70
+ console.warn(`[genai-lite:warn] ${message}`, ...args);
71
+ }
72
+ },
73
+ error(message, ...args) {
74
+ if (threshold >= LOG_LEVEL_VALUES.error) {
75
+ console.error(`[genai-lite:error] ${message}`, ...args);
76
+ }
77
+ },
78
+ };
79
+ }
80
+ /**
81
+ * A silent logger that discards all output.
82
+ * Useful for testing or when logging should be completely disabled.
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const service = new LLMService(apiKeyProvider, { logger: silentLogger });
87
+ * ```
88
+ */
89
+ exports.silentLogger = {
90
+ debug: () => { },
91
+ info: () => { },
92
+ warn: () => { },
93
+ error: () => { },
94
+ };
@@ -0,0 +1,2 @@
1
+ export type { Logger, LogLevel, LoggingConfig } from './types';
2
+ export { createDefaultLogger, DEFAULT_LOG_LEVEL, silentLogger, } from './defaultLogger';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.silentLogger = exports.DEFAULT_LOG_LEVEL = exports.createDefaultLogger = void 0;
4
+ var defaultLogger_1 = require("./defaultLogger");
5
+ Object.defineProperty(exports, "createDefaultLogger", { enumerable: true, get: function () { return defaultLogger_1.createDefaultLogger; } });
6
+ Object.defineProperty(exports, "DEFAULT_LOG_LEVEL", { enumerable: true, get: function () { return defaultLogger_1.DEFAULT_LOG_LEVEL; } });
7
+ Object.defineProperty(exports, "silentLogger", { enumerable: true, get: function () { return defaultLogger_1.silentLogger; } });
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Log level type - ordered from most quiet to most verbose
3
+ */
4
+ export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
5
+ /**
6
+ * Logger interface compatible with popular logging libraries
7
+ * (pino, winston, bunyan, console all have these methods)
8
+ */
9
+ export interface Logger {
10
+ debug(message: string, ...args: unknown[]): void;
11
+ info(message: string, ...args: unknown[]): void;
12
+ warn(message: string, ...args: unknown[]): void;
13
+ error(message: string, ...args: unknown[]): void;
14
+ }
15
+ /**
16
+ * Configuration for the logging system
17
+ */
18
+ export interface LoggingConfig {
19
+ /** Log level threshold - messages below this level are suppressed */
20
+ level: LogLevel;
21
+ /** Custom logger implementation (optional) */
22
+ logger?: Logger;
23
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -10,6 +10,9 @@ exports.parseStructuredContent = parseStructuredContent;
10
10
  exports.extractInitialTaggedContent = extractInitialTaggedContent;
11
11
  exports.parseRoleTags = parseRoleTags;
12
12
  exports.parseTemplateWithMetadata = parseTemplateWithMetadata;
13
+ const defaultLogger_1 = require("../logging/defaultLogger");
14
+ // Module-level logger for utility functions
15
+ const logger = (0, defaultLogger_1.createDefaultLogger)();
13
16
  /**
14
17
  * Parses a string containing structured data wrapped in custom XML-style tags.
15
18
  *
@@ -183,7 +186,7 @@ function parseTemplateWithMetadata(template) {
183
186
  catch (error) {
184
187
  // If the JSON is invalid, we warn the developer and treat the <META> block
185
188
  // as regular text to avoid crashing.
186
- console.warn('Could not parse <META> block in template. Treating it as content.', error);
189
+ logger.warn('Could not parse <META> block in template. Treating it as content.', error);
187
190
  return { metadata: { settings: {} }, content: template };
188
191
  }
189
192
  }
@@ -1,3 +1,4 @@
1
+ import type { Logger } from "../../logging/types";
1
2
  /**
2
3
  * Information about a registered adapter
3
4
  */
@@ -50,12 +51,14 @@ export declare class AdapterRegistry<TAdapter, TProviderId extends string> {
50
51
  private adapters;
51
52
  private fallbackAdapter;
52
53
  private supportedProviders;
54
+ private logger;
53
55
  /**
54
56
  * Creates a new AdapterRegistry
55
57
  *
56
58
  * @param config - Configuration for the registry
59
+ * @param logger - Optional logger instance
57
60
  */
58
- constructor(config: AdapterRegistryConfig<TAdapter, TProviderId>);
61
+ constructor(config: AdapterRegistryConfig<TAdapter, TProviderId>, logger?: Logger);
59
62
  /**
60
63
  * Initializes adapters for all supported providers using constructors
61
64
  */
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AdapterRegistry = void 0;
4
+ const defaultLogger_1 = require("../../logging/defaultLogger");
4
5
  /**
5
6
  * Generic registry for managing service adapters across different providers.
6
7
  * Handles adapter initialization, registration, and retrieval.
@@ -13,11 +14,13 @@ class AdapterRegistry {
13
14
  * Creates a new AdapterRegistry
14
15
  *
15
16
  * @param config - Configuration for the registry
17
+ * @param logger - Optional logger instance
16
18
  */
17
- constructor(config) {
19
+ constructor(config, logger) {
18
20
  this.adapters = new Map();
19
21
  this.fallbackAdapter = config.fallbackAdapter;
20
22
  this.supportedProviders = config.supportedProviders;
23
+ this.logger = logger ?? (0, defaultLogger_1.createDefaultLogger)();
21
24
  // Register custom adapters first if provided
22
25
  if (config.customAdapters) {
23
26
  for (const [providerId, adapter] of Object.entries(config.customAdapters)) {
@@ -39,7 +42,7 @@ class AdapterRegistry {
39
42
  const providerId = provider.id;
40
43
  // Skip if adapter is already registered (from custom adapters)
41
44
  if (this.adapters.has(providerId)) {
42
- console.log(`AdapterRegistry: Skipping constructor initialization for '${provider.id}' ` +
45
+ this.logger.debug(`AdapterRegistry: Skipping constructor initialization for '${provider.id}' ` +
43
46
  `(custom adapter already registered)`);
44
47
  continue;
45
48
  }
@@ -53,21 +56,21 @@ class AdapterRegistry {
53
56
  successfullyRegisteredProviders.push(provider.id);
54
57
  }
55
58
  catch (error) {
56
- console.error(`AdapterRegistry: Failed to instantiate adapter for provider '${provider.id}'. ` +
59
+ this.logger.error(`AdapterRegistry: Failed to instantiate adapter for provider '${provider.id}'. ` +
57
60
  `This provider will use the fallback adapter. Error:`, error);
58
61
  }
59
62
  }
60
63
  else {
61
- console.warn(`AdapterRegistry: No adapter constructor found for supported provider '${provider.id}'. ` +
64
+ this.logger.warn(`AdapterRegistry: No adapter constructor found for supported provider '${provider.id}'. ` +
62
65
  `This provider will use the fallback adapter.`);
63
66
  }
64
67
  }
65
68
  if (registeredCount > 0) {
66
- console.log(`AdapterRegistry: Initialized with ${registeredCount} dynamically registered adapter(s) ` +
69
+ this.logger.debug(`AdapterRegistry: Initialized with ${registeredCount} dynamically registered adapter(s) ` +
67
70
  `for: ${successfullyRegisteredProviders.join(', ')}.`);
68
71
  }
69
72
  else {
70
- console.log(`AdapterRegistry: No real adapters were dynamically registered. ` +
73
+ this.logger.debug(`AdapterRegistry: No real adapters were dynamically registered. ` +
71
74
  `All providers will use the fallback adapter.`);
72
75
  }
73
76
  }
@@ -79,7 +82,7 @@ class AdapterRegistry {
79
82
  */
80
83
  registerAdapter(providerId, adapter) {
81
84
  this.adapters.set(providerId, adapter);
82
- console.log(`AdapterRegistry: Registered adapter for provider: ${providerId}`);
85
+ this.logger.debug(`AdapterRegistry: Registered adapter for provider: ${providerId}`);
83
86
  }
84
87
  /**
85
88
  * Gets the appropriate adapter for a provider
@@ -91,11 +94,11 @@ class AdapterRegistry {
91
94
  // Check for registered real adapters first
92
95
  const registeredAdapter = this.adapters.get(providerId);
93
96
  if (registeredAdapter) {
94
- console.log(`AdapterRegistry: Using registered adapter for provider: ${providerId}`);
97
+ this.logger.debug(`AdapterRegistry: Using registered adapter for provider: ${providerId}`);
95
98
  return registeredAdapter;
96
99
  }
97
100
  // Fall back to fallback adapter for unsupported providers
98
- console.log(`AdapterRegistry: No real adapter found for ${providerId}, using fallback adapter`);
101
+ this.logger.debug(`AdapterRegistry: No real adapter found for ${providerId}, using fallback adapter`);
99
102
  return this.fallbackAdapter;
100
103
  }
101
104
  /**
@@ -4,6 +4,7 @@
4
4
  * This module contains all types for the ImageService and image generation adapters.
5
5
  * Based on the design specification in docs/devlog/2025-10-22-genai-lite-image-api-design.md
6
6
  */
7
+ import type { Logger, LogLevel } from '../logging/types';
7
8
  /**
8
9
  * Image provider ID type - represents a unique identifier for an image generation provider
9
10
  */
@@ -387,6 +388,10 @@ export interface ImageServiceOptions {
387
388
  adapters?: Record<ImageProviderId, ImageProviderAdapter>;
388
389
  /** Override default base URLs per provider */
389
390
  baseUrls?: Record<ImageProviderId, string>;
391
+ /** Log level for filtering messages. Defaults to GENAI_LITE_LOG_LEVEL env var or 'warn'. */
392
+ logLevel?: LogLevel;
393
+ /** Custom logger implementation. If provided, logLevel is ignored. */
394
+ logger?: Logger;
390
395
  }
391
396
  /**
392
397
  * Result from createPrompt utility
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genai-lite",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "A lightweight, portable toolkit for interacting with various Generative AI APIs.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",