genai-lite 0.3.2 → 0.4.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.
@@ -114,14 +114,35 @@ describe('ModelResolver', () => {
114
114
  expect(result.error?.error.message).toContain('Unsupported provider');
115
115
  expect(result.error?.error.message).toContain('Supported providers:');
116
116
  });
117
- it('should return error for unsupported model', () => {
117
+ it('should create fallback model info for unknown models (with warning)', () => {
118
+ const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();
118
119
  const result = resolver.resolve({
119
120
  providerId: 'openai',
120
121
  modelId: 'unsupported-model'
121
122
  });
122
- expect(result.error).toBeDefined();
123
- expect(result.error?.error.code).toBe('UNSUPPORTED_MODEL');
124
- expect(result.error?.error.message).toContain('Unsupported model: unsupported-model');
123
+ // Should succeed with fallback, not error
124
+ expect(result.error).toBeUndefined();
125
+ expect(result.modelInfo).toBeDefined();
126
+ expect(result.modelInfo?.id).toBe('unsupported-model');
127
+ expect(result.modelInfo?.providerId).toBe('openai');
128
+ // Should warn about unknown model
129
+ expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('Unknown model "unsupported-model"'));
130
+ consoleWarnSpy.mockRestore();
131
+ });
132
+ it('should silently create fallback for llamacpp unknown models (no warning)', () => {
133
+ const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();
134
+ const result = resolver.resolve({
135
+ providerId: 'llamacpp',
136
+ modelId: 'my-custom-gguf-model'
137
+ });
138
+ // Should succeed with fallback, not error
139
+ expect(result.error).toBeUndefined();
140
+ expect(result.modelInfo).toBeDefined();
141
+ expect(result.modelInfo?.id).toBe('my-custom-gguf-model');
142
+ expect(result.modelInfo?.providerId).toBe('llamacpp');
143
+ // Should NOT warn (llamacpp allows unknown models silently)
144
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
145
+ consoleWarnSpy.mockRestore();
125
146
  });
126
147
  it('should pass through user settings for direct resolution', () => {
127
148
  const settings = {
@@ -167,6 +167,8 @@ export interface LLMFailureResponse {
167
167
  model?: string;
168
168
  error: LLMError;
169
169
  object: 'error';
170
+ /** The partial response that was generated before the error occurred (if available) */
171
+ partialResponse?: Omit<LLMResponse, 'object'>;
170
172
  }
171
173
  /**
172
174
  * Information about a supported LLM provider
@@ -175,6 +177,12 @@ export interface ProviderInfo {
175
177
  id: ApiProviderId;
176
178
  name: string;
177
179
  unsupportedParameters?: (keyof LLMSettings)[];
180
+ /**
181
+ * If true, allows using unknown/unregistered model IDs with this provider.
182
+ * Useful for providers like llamacpp where users load arbitrary models.
183
+ * Default: false (strict validation)
184
+ */
185
+ allowUnknownModels?: boolean;
178
186
  }
179
187
  /**
180
188
  * Reasoning/thinking capabilities for a model
@@ -4,5 +4,9 @@ import type { ApiKeyProvider } from "../types";
4
4
  * It looks for variables in the format: PROVIDERID_API_KEY (e.g., OPENAI_API_KEY).
5
5
  * This is a secure and standard practice for server-side applications.
6
6
  * Note: Provider IDs are converted to uppercase.
7
+ *
8
+ * Special handling:
9
+ * - llamacpp: Returns 'not-needed' (local server, no authentication)
10
+ * - mock: Returns 'not-needed' (test provider, no authentication)
7
11
  */
8
12
  export declare const fromEnvironment: ApiKeyProvider;
@@ -6,8 +6,16 @@ exports.fromEnvironment = void 0;
6
6
  * It looks for variables in the format: PROVIDERID_API_KEY (e.g., OPENAI_API_KEY).
7
7
  * This is a secure and standard practice for server-side applications.
8
8
  * Note: Provider IDs are converted to uppercase.
9
+ *
10
+ * Special handling:
11
+ * - llamacpp: Returns 'not-needed' (local server, no authentication)
12
+ * - mock: Returns 'not-needed' (test provider, no authentication)
9
13
  */
10
14
  const fromEnvironment = async (providerId) => {
15
+ // Providers that don't require API keys (local/test providers)
16
+ if (providerId === 'llamacpp' || providerId === 'mock') {
17
+ return 'not-needed';
18
+ }
11
19
  const envVarName = `${providerId.toUpperCase()}_API_KEY`;
12
20
  return process.env[envVarName] || null;
13
21
  };
@@ -43,4 +43,17 @@ describe('fromEnvironment', () => {
43
43
  const key = await (0, fromEnvironment_1.fromEnvironment)('empty');
44
44
  expect(key).toBeNull(); // Empty string is falsy, so || null returns null
45
45
  });
46
+ it('should return "not-needed" for llamacpp provider', async () => {
47
+ const key = await (0, fromEnvironment_1.fromEnvironment)('llamacpp');
48
+ expect(key).toBe('not-needed');
49
+ });
50
+ it('should return "not-needed" for mock provider', async () => {
51
+ const key = await (0, fromEnvironment_1.fromEnvironment)('mock');
52
+ expect(key).toBe('not-needed');
53
+ });
54
+ it('should return "not-needed" for llamacpp even if environment variable exists', async () => {
55
+ process.env.LLAMACPP_API_KEY = 'should-not-be-used';
56
+ const key = await (0, fromEnvironment_1.fromEnvironment)('llamacpp');
57
+ expect(key).toBe('not-needed');
58
+ });
46
59
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genai-lite",
3
- "version": "0.3.2",
3
+ "version": "0.4.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",