@jupyterlite/ai 0.14.0 → 0.16.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.
- package/lib/agent.d.ts +33 -115
- package/lib/agent.js +192 -106
- package/lib/chat-model-handler.d.ts +9 -11
- package/lib/chat-model-handler.js +9 -4
- package/lib/chat-model.d.ts +84 -13
- package/lib/chat-model.js +214 -136
- package/lib/completion/completion-provider.d.ts +2 -3
- package/lib/components/completion-status.d.ts +2 -2
- package/lib/components/index.d.ts +1 -1
- package/lib/components/index.js +1 -1
- package/lib/components/model-select.d.ts +3 -3
- package/lib/components/save-button.d.ts +31 -0
- package/lib/components/save-button.js +41 -0
- package/lib/components/tool-select.d.ts +3 -4
- package/lib/components/{token-usage-display.d.ts → usage-display.d.ts} +13 -14
- package/lib/components/usage-display.js +109 -0
- package/lib/diff-manager.d.ts +2 -3
- package/lib/index.d.ts +2 -4
- package/lib/index.js +186 -28
- package/lib/models/settings-model.d.ts +11 -53
- package/lib/models/settings-model.js +38 -22
- package/lib/providers/built-in-providers.js +22 -36
- package/lib/providers/generated-context-windows.d.ts +8 -0
- package/lib/providers/generated-context-windows.js +96 -0
- package/lib/providers/model-info.d.ts +3 -0
- package/lib/providers/model-info.js +58 -0
- package/lib/tokens.d.ts +361 -36
- package/lib/tokens.js +18 -13
- package/lib/tools/commands.d.ts +2 -3
- package/lib/widgets/ai-settings.d.ts +3 -5
- package/lib/widgets/ai-settings.js +12 -0
- package/lib/widgets/main-area-chat.d.ts +2 -3
- package/lib/widgets/main-area-chat.js +12 -12
- package/lib/widgets/provider-config-dialog.d.ts +1 -2
- package/lib/widgets/provider-config-dialog.js +34 -34
- package/package.json +17 -10
- package/schema/settings-model.json +18 -1
- package/src/agent.ts +275 -248
- package/src/chat-model-handler.ts +25 -21
- package/src/chat-model.ts +307 -196
- package/src/completion/completion-provider.ts +7 -4
- package/src/components/completion-status.tsx +3 -3
- package/src/components/index.ts +1 -1
- package/src/components/model-select.tsx +4 -3
- package/src/components/save-button.tsx +84 -0
- package/src/components/tool-select.tsx +10 -4
- package/src/components/usage-display.tsx +208 -0
- package/src/diff-manager.ts +4 -4
- package/src/index.ts +250 -58
- package/src/models/settings-model.ts +46 -88
- package/src/providers/built-in-providers.ts +22 -36
- package/src/providers/generated-context-windows.ts +102 -0
- package/src/providers/model-info.ts +88 -0
- package/src/tokens.ts +438 -58
- package/src/tools/commands.ts +2 -3
- package/src/widgets/ai-settings.tsx +69 -15
- package/src/widgets/main-area-chat.ts +18 -15
- package/src/widgets/provider-config-dialog.tsx +96 -61
- package/style/base.css +17 -195
- package/lib/approval-buttons.d.ts +0 -49
- package/lib/approval-buttons.js +0 -79
- package/lib/components/token-usage-display.js +0 -72
- package/src/approval-buttons.ts +0 -115
- package/src/components/token-usage-display.tsx +0 -138
|
@@ -1,74 +1,16 @@
|
|
|
1
1
|
import { VDomModel } from '@jupyterlab/ui-components';
|
|
2
2
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
supportsFillInMiddle?: boolean;
|
|
11
|
-
useFilterText?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface IProviderConfig {
|
|
15
|
-
id: string;
|
|
16
|
-
name: string;
|
|
17
|
-
provider: string;
|
|
18
|
-
model: string;
|
|
19
|
-
apiKey?: string;
|
|
20
|
-
baseURL?: string;
|
|
21
|
-
headers?: Record<string, string>;
|
|
22
|
-
parameters?: IProviderParameters;
|
|
23
|
-
customSettings?: Record<string, any>;
|
|
24
|
-
[key: string]: any; // Index signature for JupyterLab settings compatibility
|
|
25
|
-
}
|
|
4
|
+
import {
|
|
5
|
+
IAIConfig,
|
|
6
|
+
IAISettingsModel,
|
|
7
|
+
IMCPServerConfig,
|
|
8
|
+
IProviderConfig
|
|
9
|
+
} from '../tokens';
|
|
26
10
|
|
|
27
|
-
|
|
28
|
-
id: string;
|
|
29
|
-
name: string;
|
|
30
|
-
url: string;
|
|
31
|
-
enabled: boolean;
|
|
32
|
-
[key: string]: any; // Index signature for JupyterLab settings compatibility
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface IAIConfig {
|
|
36
|
-
// Whether to use the secrets manager
|
|
37
|
-
useSecretsManager: boolean;
|
|
38
|
-
// List of configured providers
|
|
39
|
-
providers: IProviderConfig[];
|
|
40
|
-
// Active provider IDs for different use cases
|
|
41
|
-
defaultProvider: string; // Default provider for chat
|
|
42
|
-
activeCompleterProvider?: string; // Provider for completions (if different)
|
|
43
|
-
// When true, use the same provider for chat and completions
|
|
44
|
-
useSameProviderForChatAndCompleter: boolean;
|
|
45
|
-
// MCP servers configuration
|
|
46
|
-
mcpServers: IMCPServerConfig[];
|
|
47
|
-
// Global settings
|
|
48
|
-
contextAwareness: boolean;
|
|
49
|
-
codeExecution: boolean;
|
|
50
|
-
systemPrompt: string;
|
|
51
|
-
completionSystemPrompt: string;
|
|
52
|
-
toolsEnabled: boolean;
|
|
53
|
-
// Chat behavior settings
|
|
54
|
-
sendWithShiftEnter: boolean;
|
|
55
|
-
// Token usage display setting
|
|
56
|
-
showTokenUsage: boolean;
|
|
57
|
-
// Commands that require approval before execution
|
|
58
|
-
commandsRequiringApproval: string[];
|
|
59
|
-
// Commands whose execute_command outputs may auto-render MIME bundles in chat
|
|
60
|
-
commandsAutoRenderMimeBundles: string[];
|
|
61
|
-
// MIME types that are trusted when auto-rendering execute_command outputs
|
|
62
|
-
trustedMimeTypesForAutoRender: string[];
|
|
63
|
-
// Diff display settings
|
|
64
|
-
showCellDiff: boolean;
|
|
65
|
-
showFileDiff: boolean;
|
|
66
|
-
diffDisplayMode: 'split' | 'unified';
|
|
67
|
-
// Paths to directories containing agent skills
|
|
68
|
-
skillsPaths: string[];
|
|
69
|
-
}
|
|
11
|
+
const PLUGIN_ID = '@jupyterlite/ai:settings-model';
|
|
70
12
|
|
|
71
|
-
export class AISettingsModel extends VDomModel {
|
|
13
|
+
export class AISettingsModel extends VDomModel implements IAISettingsModel {
|
|
72
14
|
private _config: IAIConfig = {
|
|
73
15
|
useSecretsManager: true,
|
|
74
16
|
providers: [],
|
|
@@ -81,10 +23,12 @@ export class AISettingsModel extends VDomModel {
|
|
|
81
23
|
toolsEnabled: true,
|
|
82
24
|
sendWithShiftEnter: false,
|
|
83
25
|
showTokenUsage: false,
|
|
26
|
+
showContextUsage: false,
|
|
84
27
|
showCellDiff: true,
|
|
85
28
|
showFileDiff: true,
|
|
86
29
|
diffDisplayMode: 'split',
|
|
87
30
|
skillsPaths: ['.agents/skills', '_agents/skills'],
|
|
31
|
+
chatBackupDirectory: '',
|
|
88
32
|
commandsRequiringApproval: [
|
|
89
33
|
'notebook:restart-run-all',
|
|
90
34
|
'notebook:run-cell',
|
|
@@ -166,6 +110,15 @@ When asked to run code or perform computations, choose the most appropriate appr
|
|
|
166
110
|
|
|
167
111
|
This means if the user asks you to "calculate the factorial of 100" or "check what library version is installed", run that directly with the jupyterlab-ai-commands kernel execution command rather than creating a new notebook file.
|
|
168
112
|
|
|
113
|
+
## Notebook State and Cell Identity
|
|
114
|
+
When working with an existing notebook, use the notebook's current structure and kernel state as the source of truth.
|
|
115
|
+
- Before changing notebook content or structure, inspect the notebook and any target cells with the relevant notebook commands you have discovered.
|
|
116
|
+
- If the user may have edited the notebook, or if a previous command could have changed it, refresh your view before continuing rather than relying on earlier results.
|
|
117
|
+
- Treat variables from previously executed cells as part of the active kernel state. When the user asks you to work with existing data or variables, use them by name instead of recreating them unless the user asks you to redefine them or the kernel state is unavailable.
|
|
118
|
+
- Be explicit about the kind of cell reference you are using. A visible execution count (for example In [6]), a notebook position, and an internal cell ID or UUID are different identifiers and may not match.
|
|
119
|
+
- When the user identifies a cell by execution count, relative position, or content, verify the target cell from the current notebook contents before editing it or inserting cells relative to it.
|
|
120
|
+
- For relative insertions, anchor the change to the confirmed target cell rather than to empty placeholder or trailing cells unless the user explicitly refers to those cells.
|
|
121
|
+
|
|
169
122
|
## Your Approach
|
|
170
123
|
- **Context-aware**: You understand the user is working in a data science/research environment
|
|
171
124
|
- **Practical**: You focus on actionable solutions that work in the user's current setup
|
|
@@ -209,7 +162,7 @@ Guidelines:
|
|
|
209
162
|
|
|
210
163
|
## Multi-Step Task Handling
|
|
211
164
|
When users request complex tasks, you use the command system to accomplish them:
|
|
212
|
-
- For file and notebook operations, use discover_commands with query 'jupyterlab-ai-commands' to find the curated set of AI commands (~
|
|
165
|
+
- For file and notebook operations, use discover_commands with query 'jupyterlab-ai-commands' to find the curated set of AI commands (~22 commands)
|
|
213
166
|
- For other JupyterLab operations (terminal, launcher, UI), use specific keywords like 'terminal', 'launcher', etc.
|
|
214
167
|
- IMPORTANT: Always use 'jupyterlab-ai-commands' as the query for file/notebook tasks - this returns a focused set instead of 100+ generic commands
|
|
215
168
|
- For example, to create a notebook with cells:
|
|
@@ -251,16 +204,16 @@ Rules:
|
|
|
251
204
|
constructor(options: AISettingsModel.IOptions) {
|
|
252
205
|
super();
|
|
253
206
|
this._settingRegistry = options.settingRegistry;
|
|
254
|
-
this.
|
|
207
|
+
this._initializeSettings();
|
|
255
208
|
}
|
|
256
209
|
|
|
257
|
-
private async
|
|
210
|
+
private async _initializeSettings(): Promise<void> {
|
|
258
211
|
try {
|
|
259
212
|
this._settings = await this._settingRegistry.load(PLUGIN_ID);
|
|
260
|
-
this.
|
|
213
|
+
this._loadFromSettings();
|
|
261
214
|
|
|
262
215
|
// Listen for settings changes
|
|
263
|
-
this._settings.changed.connect(this.
|
|
216
|
+
this._settings.changed.connect(this._onSettingsChanged, this);
|
|
264
217
|
|
|
265
218
|
this.stateChanged.emit(void 0);
|
|
266
219
|
} catch (error) {
|
|
@@ -269,12 +222,12 @@ Rules:
|
|
|
269
222
|
}
|
|
270
223
|
}
|
|
271
224
|
|
|
272
|
-
private
|
|
273
|
-
this.
|
|
225
|
+
private _onSettingsChanged(): void {
|
|
226
|
+
this._loadFromSettings();
|
|
274
227
|
this.stateChanged.emit(void 0);
|
|
275
228
|
}
|
|
276
229
|
|
|
277
|
-
private
|
|
230
|
+
private _loadFromSettings(): void {
|
|
278
231
|
if (!this._settings) {
|
|
279
232
|
return;
|
|
280
233
|
}
|
|
@@ -334,12 +287,12 @@ Rules:
|
|
|
334
287
|
// If this is the first provider, make it active
|
|
335
288
|
if (this._config.providers.length === 1) {
|
|
336
289
|
// Save both providers and defaultProvider
|
|
337
|
-
await this.
|
|
290
|
+
await this._saveSetting('providers', this._config.providers);
|
|
338
291
|
this._config.defaultProvider = id;
|
|
339
|
-
await this.
|
|
292
|
+
await this._saveSetting('defaultProvider', this._config.defaultProvider);
|
|
340
293
|
} else {
|
|
341
294
|
// Only save providers
|
|
342
|
-
await this.
|
|
295
|
+
await this._saveSetting('providers', this._config.providers);
|
|
343
296
|
}
|
|
344
297
|
|
|
345
298
|
return id;
|
|
@@ -352,18 +305,18 @@ Rules:
|
|
|
352
305
|
}
|
|
353
306
|
|
|
354
307
|
this._config.providers.splice(index, 1);
|
|
355
|
-
await this.
|
|
308
|
+
await this._saveSetting('providers', this._config.providers);
|
|
356
309
|
|
|
357
310
|
// If this was the active provider, select a new one
|
|
358
311
|
if (this._config.defaultProvider === id) {
|
|
359
312
|
this._config.defaultProvider =
|
|
360
313
|
this._config.providers.length > 0 ? this._config.providers[0].id : '';
|
|
361
|
-
await this.
|
|
314
|
+
await this._saveSetting('defaultProvider', this._config.defaultProvider);
|
|
362
315
|
}
|
|
363
316
|
|
|
364
317
|
if (this._config.activeCompleterProvider === id) {
|
|
365
318
|
this._config.activeCompleterProvider = undefined;
|
|
366
|
-
await this.
|
|
319
|
+
await this._saveSetting(
|
|
367
320
|
'activeCompleterProvider',
|
|
368
321
|
this._config.activeCompleterProvider
|
|
369
322
|
);
|
|
@@ -385,19 +338,19 @@ Rules:
|
|
|
385
338
|
delete provider[key];
|
|
386
339
|
}
|
|
387
340
|
});
|
|
388
|
-
await this.
|
|
341
|
+
await this._saveSetting('providers', this._config.providers);
|
|
389
342
|
}
|
|
390
343
|
|
|
391
344
|
async setActiveProvider(id: string): Promise<void> {
|
|
392
345
|
if (this.getProvider(id)) {
|
|
393
346
|
this._config.defaultProvider = id;
|
|
394
|
-
await this.
|
|
347
|
+
await this._saveSetting('defaultProvider', this._config.defaultProvider);
|
|
395
348
|
}
|
|
396
349
|
}
|
|
397
350
|
|
|
398
351
|
async setActiveCompleterProvider(id: string | undefined): Promise<void> {
|
|
399
352
|
this._config.activeCompleterProvider = id;
|
|
400
|
-
await this.
|
|
353
|
+
await this._saveSetting(
|
|
401
354
|
'activeCompleterProvider',
|
|
402
355
|
this._config.activeCompleterProvider
|
|
403
356
|
);
|
|
@@ -423,7 +376,7 @@ Rules:
|
|
|
423
376
|
};
|
|
424
377
|
|
|
425
378
|
this._config.mcpServers.push(newServer);
|
|
426
|
-
await this.
|
|
379
|
+
await this._saveSetting('mcpServers', this._config.mcpServers);
|
|
427
380
|
return id;
|
|
428
381
|
}
|
|
429
382
|
|
|
@@ -434,7 +387,7 @@ Rules:
|
|
|
434
387
|
}
|
|
435
388
|
|
|
436
389
|
this._config.mcpServers.splice(index, 1);
|
|
437
|
-
await this.
|
|
390
|
+
await this._saveSetting('mcpServers', this._config.mcpServers);
|
|
438
391
|
}
|
|
439
392
|
|
|
440
393
|
async updateMCPServer(
|
|
@@ -447,7 +400,7 @@ Rules:
|
|
|
447
400
|
}
|
|
448
401
|
|
|
449
402
|
Object.assign(server, updates);
|
|
450
|
-
await this.
|
|
403
|
+
await this._saveSetting('mcpServers', this._config.mcpServers);
|
|
451
404
|
}
|
|
452
405
|
|
|
453
406
|
async updateConfig(updates: Partial<IAIConfig>): Promise<void> {
|
|
@@ -460,7 +413,7 @@ Rules:
|
|
|
460
413
|
this._config[key as keyof IAIConfig] !== value
|
|
461
414
|
) {
|
|
462
415
|
(this._config as any)[key] = value;
|
|
463
|
-
promises.push(this.
|
|
416
|
+
promises.push(this._saveSetting(key as keyof IAIConfig, value));
|
|
464
417
|
}
|
|
465
418
|
}
|
|
466
419
|
|
|
@@ -468,6 +421,11 @@ Rules:
|
|
|
468
421
|
await Promise.all(promises);
|
|
469
422
|
}
|
|
470
423
|
|
|
424
|
+
/**
|
|
425
|
+
* Get the API key saved in the settings file for a given provider.
|
|
426
|
+
*
|
|
427
|
+
* @param id - the id of the provider.
|
|
428
|
+
*/
|
|
471
429
|
getApiKey(id: string): string {
|
|
472
430
|
// First check the active completer provider
|
|
473
431
|
const activeCompleterProvider = this.getCompleterProvider();
|
|
@@ -484,7 +442,7 @@ Rules:
|
|
|
484
442
|
return '';
|
|
485
443
|
}
|
|
486
444
|
|
|
487
|
-
private async
|
|
445
|
+
private async _saveSetting(key: keyof IAIConfig, value: any): Promise<void> {
|
|
488
446
|
try {
|
|
489
447
|
if (this._settings) {
|
|
490
448
|
// Only save the specific setting that changed
|
|
@@ -4,6 +4,7 @@ import { createMistral } from '@ai-sdk/mistral';
|
|
|
4
4
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
5
5
|
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
6
6
|
|
|
7
|
+
import { BUILT_IN_PROVIDER_MODEL_INFO } from './generated-context-windows';
|
|
7
8
|
import type { IProviderInfo } from '../tokens';
|
|
8
9
|
import type { IModelOptions } from './models';
|
|
9
10
|
|
|
@@ -28,9 +29,9 @@ export const anthropicProvider: IProviderInfo = {
|
|
|
28
29
|
'claude-opus-4-0',
|
|
29
30
|
'claude-opus-4-20250514',
|
|
30
31
|
'claude-sonnet-4-0',
|
|
31
|
-
'claude-sonnet-4-20250514'
|
|
32
|
-
'claude-3-haiku-20240307'
|
|
32
|
+
'claude-sonnet-4-20250514'
|
|
33
33
|
],
|
|
34
|
+
modelInfo: BUILT_IN_PROVIDER_MODEL_INFO.anthropic,
|
|
34
35
|
supportsBaseURL: true,
|
|
35
36
|
supportsHeaders: true,
|
|
36
37
|
providerToolCapabilities: {
|
|
@@ -65,30 +66,20 @@ export const googleProvider: IProviderInfo = {
|
|
|
65
66
|
'gemini-3.1-pro-preview',
|
|
66
67
|
'gemini-3.1-pro-preview-customtools',
|
|
67
68
|
'gemini-3.1-flash-image-preview',
|
|
68
|
-
'gemini-3-
|
|
69
|
+
'gemini-3.1-flash-lite-preview',
|
|
69
70
|
'gemini-3-pro-image-preview',
|
|
70
71
|
'gemini-3-flash-preview',
|
|
71
72
|
'gemini-2.5-pro',
|
|
72
73
|
'gemini-2.5-flash',
|
|
73
74
|
'gemini-2.5-flash-image',
|
|
74
75
|
'gemini-2.5-flash-lite',
|
|
75
|
-
'gemini-2.5-flash-lite-preview-09-2025',
|
|
76
76
|
'gemini-2.5-computer-use-preview-10-2025',
|
|
77
|
-
'
|
|
78
|
-
'gemini-2.0-flash-001',
|
|
79
|
-
'gemini-2.0-flash-lite',
|
|
80
|
-
'gemini-2.0-flash-lite-001',
|
|
77
|
+
'deep-research-pro-preview-12-2025',
|
|
81
78
|
'gemini-pro-latest',
|
|
82
79
|
'gemini-flash-latest',
|
|
83
|
-
'gemini-flash-lite-latest'
|
|
84
|
-
'deep-research-pro-preview-12-2025',
|
|
85
|
-
'gemma-3-27b-it',
|
|
86
|
-
'gemma-3-12b-it',
|
|
87
|
-
'gemma-3-4b-it',
|
|
88
|
-
'gemma-3-1b-it',
|
|
89
|
-
'gemma-3n-e4b-it',
|
|
90
|
-
'gemma-3n-e2b-it'
|
|
80
|
+
'gemini-flash-lite-latest'
|
|
91
81
|
],
|
|
82
|
+
modelInfo: BUILT_IN_PROVIDER_MODEL_INFO.google,
|
|
92
83
|
supportsBaseURL: true,
|
|
93
84
|
factory: (options: IModelOptions) => {
|
|
94
85
|
if (!options.apiKey) {
|
|
@@ -111,24 +102,21 @@ export const mistralProvider: IProviderInfo = {
|
|
|
111
102
|
name: 'Mistral AI',
|
|
112
103
|
apiKeyRequirement: 'required',
|
|
113
104
|
defaultModels: [
|
|
114
|
-
'ministral-3b-latest',
|
|
115
|
-
'ministral-8b-latest',
|
|
116
105
|
'mistral-large-latest',
|
|
117
106
|
'mistral-medium-latest',
|
|
118
107
|
'mistral-medium-2508',
|
|
119
|
-
'mistral-medium-2505',
|
|
120
108
|
'mistral-small-latest',
|
|
121
|
-
'
|
|
109
|
+
'mistral-small-2506',
|
|
110
|
+
'ministral-3b-latest',
|
|
111
|
+
'ministral-8b-latest',
|
|
112
|
+
'ministral-14b-latest',
|
|
113
|
+
'magistral-small-latest',
|
|
114
|
+
'magistral-medium-latest',
|
|
122
115
|
'pixtral-large-latest',
|
|
123
|
-
'
|
|
124
|
-
'
|
|
125
|
-
'magistral-small-2506',
|
|
126
|
-
'magistral-medium-2506',
|
|
127
|
-
'pixtral-12b-2409',
|
|
128
|
-
'open-mistral-7b',
|
|
129
|
-
'open-mixtral-8x7b',
|
|
130
|
-
'open-mixtral-8x22b'
|
|
116
|
+
'codestral-latest',
|
|
117
|
+
'devstral-latest'
|
|
131
118
|
],
|
|
119
|
+
modelInfo: BUILT_IN_PROVIDER_MODEL_INFO.mistral,
|
|
132
120
|
supportsBaseURL: true,
|
|
133
121
|
factory: (options: IModelOptions) => {
|
|
134
122
|
if (!options.apiKey) {
|
|
@@ -151,6 +139,9 @@ export const openaiProvider: IProviderInfo = {
|
|
|
151
139
|
name: 'OpenAI',
|
|
152
140
|
apiKeyRequirement: 'required',
|
|
153
141
|
defaultModels: [
|
|
142
|
+
'gpt-5.4',
|
|
143
|
+
'gpt-5.4-mini',
|
|
144
|
+
'gpt-5.4-nano',
|
|
154
145
|
'gpt-5.2',
|
|
155
146
|
'gpt-5.2-2025-12-11',
|
|
156
147
|
'gpt-5.2-chat-latest',
|
|
@@ -169,6 +160,7 @@ export const openaiProvider: IProviderInfo = {
|
|
|
169
160
|
'gpt-5-nano-2025-08-07',
|
|
170
161
|
'o4-mini',
|
|
171
162
|
'o4-mini-2025-04-16',
|
|
163
|
+
'o3-pro',
|
|
172
164
|
'o3',
|
|
173
165
|
'o3-2025-04-16',
|
|
174
166
|
'o3-mini',
|
|
@@ -185,22 +177,16 @@ export const openaiProvider: IProviderInfo = {
|
|
|
185
177
|
'gpt-4o-2024-05-13',
|
|
186
178
|
'gpt-4o-2024-08-06',
|
|
187
179
|
'gpt-4o-2024-11-20',
|
|
188
|
-
'gpt-4o-audio-preview',
|
|
189
|
-
'gpt-4o-audio-preview-2024-12-17',
|
|
190
|
-
'gpt-4o-audio-preview-2025-06-03',
|
|
191
180
|
'gpt-4o-mini',
|
|
192
181
|
'gpt-4o-mini-2024-07-18',
|
|
193
|
-
'gpt-4o-mini-audio-preview',
|
|
194
|
-
'gpt-4o-mini-audio-preview-2024-12-17',
|
|
195
182
|
'gpt-4o-search-preview',
|
|
196
183
|
'gpt-4o-search-preview-2025-03-11',
|
|
197
184
|
'gpt-4o-mini-search-preview',
|
|
198
185
|
'gpt-4o-mini-search-preview-2025-03-11',
|
|
199
186
|
'gpt-3.5-turbo',
|
|
200
|
-
'gpt-3.5-turbo-0125'
|
|
201
|
-
'gpt-3.5-turbo-1106',
|
|
202
|
-
'gpt-3.5-turbo-16k'
|
|
187
|
+
'gpt-3.5-turbo-0125'
|
|
203
188
|
],
|
|
189
|
+
modelInfo: BUILT_IN_PROVIDER_MODEL_INFO.openai,
|
|
204
190
|
supportsBaseURL: true,
|
|
205
191
|
supportsHeaders: true,
|
|
206
192
|
providerToolCapabilities: {
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is generated by `jlpm sync:model-context-windows`.
|
|
3
|
+
* Source: https://models.dev/api.json
|
|
4
|
+
* Backed by: https://github.com/anomalyco/models.dev
|
|
5
|
+
* Generated: 2026-04-08T16:23:34.080Z
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { IProviderModelInfo } from '../tokens';
|
|
9
|
+
|
|
10
|
+
export const BUILT_IN_PROVIDER_MODEL_INFO: Record<
|
|
11
|
+
string,
|
|
12
|
+
Record<string, IProviderModelInfo>
|
|
13
|
+
> = {
|
|
14
|
+
anthropic: {
|
|
15
|
+
'claude-opus-4-6': { contextWindow: 1000000 },
|
|
16
|
+
'claude-sonnet-4-6': { contextWindow: 1000000 },
|
|
17
|
+
'claude-opus-4-5': { contextWindow: 200000 },
|
|
18
|
+
'claude-opus-4-5-20251101': { contextWindow: 200000 },
|
|
19
|
+
'claude-sonnet-4-5': { contextWindow: 200000 },
|
|
20
|
+
'claude-sonnet-4-5-20250929': { contextWindow: 200000 },
|
|
21
|
+
'claude-haiku-4-5': { contextWindow: 200000 },
|
|
22
|
+
'claude-haiku-4-5-20251001': { contextWindow: 200000 },
|
|
23
|
+
'claude-opus-4-1': { contextWindow: 200000 },
|
|
24
|
+
'claude-opus-4-1-20250805': { contextWindow: 200000 },
|
|
25
|
+
'claude-opus-4-0': { contextWindow: 200000 },
|
|
26
|
+
'claude-opus-4-20250514': { contextWindow: 200000 },
|
|
27
|
+
'claude-sonnet-4-0': { contextWindow: 200000 },
|
|
28
|
+
'claude-sonnet-4-20250514': { contextWindow: 200000 }
|
|
29
|
+
},
|
|
30
|
+
google: {
|
|
31
|
+
'gemini-3.1-pro-preview': { contextWindow: 1048576 },
|
|
32
|
+
'gemini-3.1-pro-preview-customtools': { contextWindow: 1048576 },
|
|
33
|
+
'gemini-3.1-flash-image-preview': { contextWindow: 131072 },
|
|
34
|
+
'gemini-3.1-flash-lite-preview': { contextWindow: 1048576 },
|
|
35
|
+
'gemini-3-flash-preview': { contextWindow: 1048576 },
|
|
36
|
+
'gemini-2.5-pro': { contextWindow: 1048576 },
|
|
37
|
+
'gemini-2.5-flash': { contextWindow: 1048576 },
|
|
38
|
+
'gemini-2.5-flash-image': { contextWindow: 32768 },
|
|
39
|
+
'gemini-2.5-flash-lite': { contextWindow: 1048576 },
|
|
40
|
+
'gemini-flash-latest': { contextWindow: 1048576 },
|
|
41
|
+
'gemini-flash-lite-latest': { contextWindow: 1048576 }
|
|
42
|
+
},
|
|
43
|
+
mistral: {
|
|
44
|
+
'mistral-large-latest': { contextWindow: 262144 },
|
|
45
|
+
'mistral-medium-latest': { contextWindow: 128000 },
|
|
46
|
+
'mistral-medium-2508': { contextWindow: 262144 },
|
|
47
|
+
'mistral-small-latest': { contextWindow: 256000 },
|
|
48
|
+
'mistral-small-2506': { contextWindow: 128000 },
|
|
49
|
+
'ministral-3b-latest': { contextWindow: 128000 },
|
|
50
|
+
'ministral-8b-latest': { contextWindow: 128000 },
|
|
51
|
+
'magistral-small-latest': { contextWindow: 128000 },
|
|
52
|
+
'magistral-medium-latest': { contextWindow: 128000 },
|
|
53
|
+
'pixtral-large-latest': { contextWindow: 128000 },
|
|
54
|
+
'codestral-latest': { contextWindow: 256000 },
|
|
55
|
+
'devstral-latest': { contextWindow: 262144 },
|
|
56
|
+
'devstral-2512': { contextWindow: 262144 }
|
|
57
|
+
},
|
|
58
|
+
openai: {
|
|
59
|
+
'gpt-5.4': { contextWindow: 1050000 },
|
|
60
|
+
'gpt-5.4-mini': { contextWindow: 400000 },
|
|
61
|
+
'gpt-5.4-nano': { contextWindow: 400000 },
|
|
62
|
+
'gpt-5.2': { contextWindow: 400000 },
|
|
63
|
+
'gpt-5.2-2025-12-11': { contextWindow: 400000 },
|
|
64
|
+
'gpt-5.2-chat-latest': { contextWindow: 128000 },
|
|
65
|
+
'gpt-5.2-pro': { contextWindow: 400000 },
|
|
66
|
+
'gpt-5.2-pro-2025-12-11': { contextWindow: 400000 },
|
|
67
|
+
'gpt-5.2-codex': { contextWindow: 400000 },
|
|
68
|
+
'gpt-5.1': { contextWindow: 400000 },
|
|
69
|
+
'gpt-5.1-2025-11-13': { contextWindow: 400000 },
|
|
70
|
+
'gpt-5.1-chat-latest': { contextWindow: 128000 },
|
|
71
|
+
'gpt-5': { contextWindow: 400000 },
|
|
72
|
+
'gpt-5-2025-08-07': { contextWindow: 400000 },
|
|
73
|
+
'gpt-5-chat-latest': { contextWindow: 400000 },
|
|
74
|
+
'gpt-5-mini': { contextWindow: 400000 },
|
|
75
|
+
'gpt-5-mini-2025-08-07': { contextWindow: 400000 },
|
|
76
|
+
'gpt-5-nano': { contextWindow: 400000 },
|
|
77
|
+
'gpt-5-nano-2025-08-07': { contextWindow: 400000 },
|
|
78
|
+
'o4-mini': { contextWindow: 200000 },
|
|
79
|
+
'o4-mini-2025-04-16': { contextWindow: 200000 },
|
|
80
|
+
'o3-pro': { contextWindow: 200000 },
|
|
81
|
+
o3: { contextWindow: 200000 },
|
|
82
|
+
'o3-2025-04-16': { contextWindow: 200000 },
|
|
83
|
+
'o3-mini': { contextWindow: 200000 },
|
|
84
|
+
'o3-mini-2025-01-31': { contextWindow: 200000 },
|
|
85
|
+
o1: { contextWindow: 200000 },
|
|
86
|
+
'o1-2024-12-17': { contextWindow: 200000 },
|
|
87
|
+
'gpt-4.1': { contextWindow: 1047576 },
|
|
88
|
+
'gpt-4.1-2025-04-14': { contextWindow: 1047576 },
|
|
89
|
+
'gpt-4.1-mini': { contextWindow: 1047576 },
|
|
90
|
+
'gpt-4.1-mini-2025-04-14': { contextWindow: 1047576 },
|
|
91
|
+
'gpt-4.1-nano': { contextWindow: 1047576 },
|
|
92
|
+
'gpt-4.1-nano-2025-04-14': { contextWindow: 1047576 },
|
|
93
|
+
'gpt-4o': { contextWindow: 128000 },
|
|
94
|
+
'gpt-4o-2024-05-13': { contextWindow: 128000 },
|
|
95
|
+
'gpt-4o-2024-08-06': { contextWindow: 128000 },
|
|
96
|
+
'gpt-4o-2024-11-20': { contextWindow: 128000 },
|
|
97
|
+
'gpt-4o-mini': { contextWindow: 128000 },
|
|
98
|
+
'gpt-4o-mini-2024-07-18': { contextWindow: 128000 },
|
|
99
|
+
'gpt-3.5-turbo': { contextWindow: 16385 },
|
|
100
|
+
'gpt-3.5-turbo-0125': { contextWindow: 16385 }
|
|
101
|
+
}
|
|
102
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
IProviderConfig,
|
|
3
|
+
IProviderInfo,
|
|
4
|
+
IProviderModelInfo,
|
|
5
|
+
IProviderRegistry
|
|
6
|
+
} from '../tokens';
|
|
7
|
+
|
|
8
|
+
const DATE_SUFFIX = /^(.*)-\d{4}-\d{2}-\d{2}$/;
|
|
9
|
+
const SHORT_VERSION_SUFFIX = /^(.*)-\d{4}$/;
|
|
10
|
+
|
|
11
|
+
// Treat rolling aliases and dated releases as the same model family so they
|
|
12
|
+
// can share provider metadata such as context windows.
|
|
13
|
+
function normalizeModelId(modelId: string): string {
|
|
14
|
+
if (modelId.endsWith('-latest')) {
|
|
15
|
+
return modelId.slice(0, -7);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const dateSuffixMatch = modelId.match(DATE_SUFFIX);
|
|
19
|
+
if (dateSuffixMatch) {
|
|
20
|
+
return dateSuffixMatch[1];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const shortVersionSuffixMatch = modelId.match(SHORT_VERSION_SUFFIX);
|
|
24
|
+
if (shortVersionSuffixMatch) {
|
|
25
|
+
return shortVersionSuffixMatch[1];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return modelId;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getCandidateModelIds(modelId: string): string[] {
|
|
32
|
+
const candidates = [modelId];
|
|
33
|
+
const normalizedModelId = normalizeModelId(modelId);
|
|
34
|
+
|
|
35
|
+
candidates.push(normalizedModelId);
|
|
36
|
+
|
|
37
|
+
if (normalizedModelId !== modelId) {
|
|
38
|
+
candidates.push(`${normalizedModelId}-latest`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return [...new Set(candidates)];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getProviderModelInfo(
|
|
45
|
+
providerInfo: IProviderInfo | null | undefined,
|
|
46
|
+
model: string | undefined
|
|
47
|
+
): IProviderModelInfo | undefined {
|
|
48
|
+
if (!providerInfo || !model) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const modelInfo = providerInfo.modelInfo;
|
|
53
|
+
if (!modelInfo) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (const candidateId of getCandidateModelIds(model)) {
|
|
58
|
+
if (modelInfo[candidateId]) {
|
|
59
|
+
return modelInfo[candidateId];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const normalizedModelId = normalizeModelId(model);
|
|
64
|
+
// As a last resort, match any known model entry that normalizes to the same
|
|
65
|
+
// base ID, even if the exact alias/version string differs.
|
|
66
|
+
return Object.entries(modelInfo).find(([candidateId]) => {
|
|
67
|
+
return normalizeModelId(candidateId) === normalizedModelId;
|
|
68
|
+
})?.[1];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function getEffectiveContextWindow(
|
|
72
|
+
providerConfig: IProviderConfig | undefined,
|
|
73
|
+
providerRegistry?: IProviderRegistry
|
|
74
|
+
): number | undefined {
|
|
75
|
+
if (!providerConfig) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (providerConfig.parameters?.contextWindow !== undefined) {
|
|
80
|
+
return providerConfig.parameters.contextWindow;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const providerInfo = providerRegistry?.getProviderInfo(
|
|
84
|
+
providerConfig.provider
|
|
85
|
+
);
|
|
86
|
+
return getProviderModelInfo(providerInfo, providerConfig.model)
|
|
87
|
+
?.contextWindow;
|
|
88
|
+
}
|