@jupyternaut/persona 0.0.0 → 0.20.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.
Files changed (49) hide show
  1. package/lib/chat-commands/mention.d.ts +9 -0
  2. package/lib/chat-commands/mention.js +30 -0
  3. package/lib/completion/completion-provider.d.ts +86 -0
  4. package/lib/completion/completion-provider.js +246 -0
  5. package/lib/completion/index.d.ts +2 -0
  6. package/lib/completion/index.js +1 -0
  7. package/lib/components/completion-status.d.ts +26 -0
  8. package/lib/components/completion-status.js +52 -0
  9. package/lib/components/index.d.ts +2 -0
  10. package/lib/components/index.js +1 -0
  11. package/lib/diff-manager.d.ts +25 -0
  12. package/lib/diff-manager.js +60 -0
  13. package/lib/index.d.ts +8 -0
  14. package/lib/index.js +522 -0
  15. package/lib/models/settings-model.d.ts +36 -0
  16. package/lib/models/settings-model.js +356 -0
  17. package/lib/persona-registry.d.ts +15 -0
  18. package/lib/persona-registry.js +29 -0
  19. package/lib/persona.d.ts +66 -0
  20. package/lib/persona.js +414 -0
  21. package/lib/process-attachments.d.ts +5 -0
  22. package/lib/process-attachments.js +287 -0
  23. package/lib/tokens.d.ts +101 -0
  24. package/lib/tokens.js +20 -0
  25. package/lib/widgets/ai-settings.d.ts +54 -0
  26. package/lib/widgets/ai-settings.js +572 -0
  27. package/lib/widgets/provider-config-dialog.d.ts +16 -0
  28. package/lib/widgets/provider-config-dialog.js +384 -0
  29. package/package.json +111 -7
  30. package/schema/settings-model.json +287 -0
  31. package/src/chat-commands/mention.tsx +46 -0
  32. package/src/completion/completion-provider.ts +350 -0
  33. package/src/completion/index.ts +1 -0
  34. package/src/components/completion-status.tsx +93 -0
  35. package/src/components/index.ts +1 -0
  36. package/src/diff-manager.ts +81 -0
  37. package/src/index.ts +710 -0
  38. package/src/models/settings-model.ts +415 -0
  39. package/src/persona-registry.ts +46 -0
  40. package/src/persona.ts +610 -0
  41. package/src/process-attachments.ts +369 -0
  42. package/src/tokens.ts +121 -0
  43. package/src/widgets/ai-settings.tsx +1308 -0
  44. package/src/widgets/provider-config-dialog.tsx +997 -0
  45. package/style/base.css +14 -0
  46. package/style/index.css +1 -0
  47. package/style/index.js +1 -0
  48. package/README.md +0 -3
  49. package/index.js +0 -1
package/lib/index.js ADDED
@@ -0,0 +1,522 @@
1
+ import { anthropicProvider, createBrowserFetchTool, createDiscoverCommandsTool, createDiscoverSkillsTool, createExecuteCommandTool, createLoadSkillTool, genericProvider, googleProvider, loadSkillsFromPaths, mistralProvider, openaiProvider, AgentManagerFactory, IAgentManagerFactory, IAISettingsModel, IDiffManager, IProviderRegistry, IToolRegistry, ISkillRegistry, ProviderRegistry, SECRETS_NAMESPACE, SkillRegistry, ToolRegistry } from '@jupyternaut/agent';
2
+ import { ILayoutRestorer } from '@jupyterlab/application';
3
+ import { IChatTracker, IChatCommandRegistry } from '@jupyter/chat';
4
+ import { ICommandPalette, IThemeManager } from '@jupyterlab/apputils';
5
+ import { ICompletionProviderManager } from '@jupyterlab/completer';
6
+ import { IDocumentManager } from '@jupyterlab/docmanager';
7
+ import { ISettingRegistry } from '@jupyterlab/settingregistry';
8
+ import { IStatusBar } from '@jupyterlab/statusbar';
9
+ import { PathExt } from '@jupyterlab/coreutils';
10
+ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
11
+ import { IFormRendererRegistry, settingsIcon } from '@jupyterlab/ui-components';
12
+ import { DisposableSet } from '@lumino/disposable';
13
+ import { IMcpManager } from 'jupyter-mcp-manager';
14
+ import { ISecretsManager, SecretsManager } from 'jupyter-secrets-manager';
15
+ import { MentionCommandProvider } from './chat-commands/mention';
16
+ import { AICompletionProvider } from './completion';
17
+ import { CompletionStatusWidget } from './components';
18
+ import { DiffManager } from './diff-manager';
19
+ import { AISettingsModel } from './models/settings-model';
20
+ import { PersonaRegistry } from './persona-registry';
21
+ import { CommandIds, IPersonaRegistry, DEFAULT_PERSONA } from './tokens';
22
+ import { AISettingsWidget } from './widgets/ai-settings';
23
+ var Private;
24
+ (function (Private) {
25
+ let aiSecretsToken = null;
26
+ function setAISecretsToken(token) {
27
+ aiSecretsToken = token;
28
+ }
29
+ Private.setAISecretsToken = setAISecretsToken;
30
+ function createAISecretsAccess(secretsManager) {
31
+ return {
32
+ get isAvailable() {
33
+ return !!(aiSecretsToken && secretsManager);
34
+ },
35
+ async get(id) {
36
+ if (!aiSecretsToken || !secretsManager) {
37
+ return;
38
+ }
39
+ const secret = await secretsManager.get(aiSecretsToken, SECRETS_NAMESPACE, id);
40
+ return secret?.value;
41
+ },
42
+ async set(id, value) {
43
+ if (!aiSecretsToken || !secretsManager) {
44
+ return;
45
+ }
46
+ await secretsManager.set(aiSecretsToken, SECRETS_NAMESPACE, id, {
47
+ namespace: SECRETS_NAMESPACE,
48
+ id,
49
+ value
50
+ });
51
+ },
52
+ async attach(id, input, callback) {
53
+ if (!aiSecretsToken || !secretsManager) {
54
+ return;
55
+ }
56
+ await secretsManager.attach(aiSecretsToken, SECRETS_NAMESPACE, id, input, callback);
57
+ }
58
+ };
59
+ }
60
+ Private.createAISecretsAccess = createAISecretsAccess;
61
+ })(Private || (Private = {}));
62
+ /**
63
+ * Provider registry plugin
64
+ */
65
+ const providerRegistryPlugin = {
66
+ id: '@jupyternaut/persona:provider-registry',
67
+ description: 'AI provider registry',
68
+ autoStart: true,
69
+ provides: IProviderRegistry,
70
+ activate: () => {
71
+ return new ProviderRegistry();
72
+ }
73
+ };
74
+ /**
75
+ * Anthropic provider plugin
76
+ */
77
+ const anthropicProviderPlugin = {
78
+ id: '@jupyternaut/persona:anthropic-provider',
79
+ description: 'Register Anthropic provider',
80
+ autoStart: true,
81
+ requires: [IProviderRegistry],
82
+ activate: (app, providerRegistry) => {
83
+ providerRegistry.registerProvider(anthropicProvider);
84
+ }
85
+ };
86
+ /**
87
+ * Google provider plugin
88
+ */
89
+ const googleProviderPlugin = {
90
+ id: '@jupyternaut/persona:google-provider',
91
+ description: 'Register Google Generative AI provider',
92
+ autoStart: true,
93
+ requires: [IProviderRegistry],
94
+ activate: (app, providerRegistry) => {
95
+ providerRegistry.registerProvider(googleProvider);
96
+ }
97
+ };
98
+ /**
99
+ * Mistral provider plugin
100
+ */
101
+ const mistralProviderPlugin = {
102
+ id: '@jupyternaut/persona:mistral-provider',
103
+ description: 'Register Mistral provider',
104
+ autoStart: true,
105
+ requires: [IProviderRegistry],
106
+ activate: (app, providerRegistry) => {
107
+ providerRegistry.registerProvider(mistralProvider);
108
+ }
109
+ };
110
+ /**
111
+ * OpenAI provider plugin
112
+ */
113
+ const openaiProviderPlugin = {
114
+ id: '@jupyternaut/persona:openai-provider',
115
+ description: 'Register OpenAI provider',
116
+ autoStart: true,
117
+ requires: [IProviderRegistry],
118
+ activate: (app, providerRegistry) => {
119
+ providerRegistry.registerProvider(openaiProvider);
120
+ }
121
+ };
122
+ /**
123
+ * Generic provider plugin
124
+ */
125
+ const genericProviderPlugin = {
126
+ id: '@jupyternaut/persona:generic-provider',
127
+ description: 'Register Generic OpenAI-compatible provider',
128
+ autoStart: true,
129
+ requires: [IProviderRegistry],
130
+ activate: (app, providerRegistry) => {
131
+ providerRegistry.registerProvider(genericProvider);
132
+ }
133
+ };
134
+ /**
135
+ * Provides the persona handler registry without any IChatTracker dependency,
136
+ * so it can be consumed by the toolbar factory without creating a plugin cycle.
137
+ */
138
+ const personaRegistry = {
139
+ id: '@jupyternaut/persona:registry',
140
+ description: 'Registry mapping chat models to their persona handlers',
141
+ autoStart: true,
142
+ provides: IPersonaRegistry,
143
+ requires: [IAISettingsModel],
144
+ optional: [IProviderRegistry, IDocumentManager],
145
+ activate: (app, settingsModel, providerRegistry, documentManager) => {
146
+ return new PersonaRegistry({
147
+ persona: DEFAULT_PERSONA,
148
+ settingsModel,
149
+ providerRegistry,
150
+ documentManager
151
+ });
152
+ }
153
+ };
154
+ /**
155
+ * Connects the persona handler registry to the chat tracker, creating a
156
+ * PersonaHandler for each chat widget that is opened.
157
+ */
158
+ const persona = {
159
+ id: '@jupyternaut/persona:plugin',
160
+ description: 'Attach persona handlers to chat widgets as they are opened',
161
+ autoStart: true,
162
+ requires: [IPersonaRegistry, IAgentManagerFactory, IAISettingsModel],
163
+ optional: [IChatTracker, IProviderRegistry, IToolRegistry],
164
+ activate: (app, registry, agentManagerFactory, settingsModel, chatTracker, providerRegistry, toolRegistry) => {
165
+ const attachPersona = (widget) => {
166
+ if (registry.get(widget.model)) {
167
+ return;
168
+ }
169
+ const agentManager = agentManagerFactory.createAgent({
170
+ settingsModel,
171
+ providerRegistry,
172
+ toolRegistry
173
+ });
174
+ registry.register(widget.model, agentManager);
175
+ widget.disposed.connect(() => {
176
+ registry.unregister(widget.model);
177
+ });
178
+ };
179
+ chatTracker?.forEach(widget => attachPersona(widget));
180
+ chatTracker?.widgetAdded.connect((_, widget) => attachPersona(widget));
181
+ }
182
+ };
183
+ /**
184
+ * Clear chat command plugin.
185
+ */
186
+ const mentionCommandPlugin = {
187
+ id: '@jupyternaut/persona:mention',
188
+ description: 'Register the Jupyternaut mention chat command.',
189
+ autoStart: true,
190
+ requires: [IChatCommandRegistry],
191
+ activate: (app, registry) => {
192
+ registry.addProvider(new MentionCommandProvider());
193
+ }
194
+ };
195
+ /**
196
+ * A plugin to provide the agent manager factory and completion provider.
197
+ * These objects require the secrets manager token with the same namespace.
198
+ */
199
+ const agentManagerFactory = SecretsManager.sign(SECRETS_NAMESPACE, token => {
200
+ Private.setAISecretsToken(token);
201
+ return {
202
+ id: SECRETS_NAMESPACE,
203
+ description: 'Provide the AI agent manager',
204
+ autoStart: true,
205
+ provides: IAgentManagerFactory,
206
+ requires: [IAISettingsModel, IProviderRegistry],
207
+ optional: [
208
+ ISkillRegistry,
209
+ ICompletionProviderManager,
210
+ ISecretsManager,
211
+ IMcpManager
212
+ ],
213
+ activate: (app, settingsModel, providerRegistry, skillRegistry, completionManager, secretsManager, mcpManager) => {
214
+ const agentManagerFactory = new AgentManagerFactory({
215
+ settingsModel,
216
+ skillRegistry,
217
+ mcpManager,
218
+ secretsManager,
219
+ token
220
+ });
221
+ // Build the completion provider
222
+ if (completionManager) {
223
+ const completionProvider = new AICompletionProvider({
224
+ settingsModel,
225
+ providerRegistry,
226
+ secretsManager,
227
+ token
228
+ });
229
+ completionManager.registerInlineProvider(completionProvider);
230
+ }
231
+ else {
232
+ console.info('Completion provider manager not available, skipping AI completion setup');
233
+ }
234
+ return agentManagerFactory;
235
+ }
236
+ };
237
+ });
238
+ /**
239
+ * AI settings panel plugin.
240
+ */
241
+ const settingsPanelPlugin = {
242
+ id: '@jupyternaut/persona:settings-panel',
243
+ description: 'Provide the AI settings panel',
244
+ autoStart: true,
245
+ requires: [IAISettingsModel, IAgentManagerFactory, IProviderRegistry],
246
+ optional: [
247
+ ICommandPalette,
248
+ ILayoutRestorer,
249
+ ISecretsManager,
250
+ IThemeManager,
251
+ ITranslator,
252
+ IFormRendererRegistry,
253
+ // This token is not used, but depending on it ensures that the renderer has been
254
+ // added to the form renderer registry.
255
+ IMcpManager
256
+ ],
257
+ activate: (app, settingsModel, agentManagerFactory, providerRegistry, palette, restorer, secretsManager, themeManager, translator, formRenderer) => {
258
+ const trans = (translator ?? nullTranslator).load('jupyterlite_ai');
259
+ const secretsAccess = Private.createAISecretsAccess(secretsManager);
260
+ // Get the renderer for MCP servers settings
261
+ const mcpServerRenderer = formRenderer?.getRenderer('jupyter-mcp-manager:manager.mcpSettings').fieldRenderer;
262
+ const settingsWidget = new AISettingsWidget({
263
+ settingsModel,
264
+ agentManagerFactory,
265
+ themeManager,
266
+ providerRegistry,
267
+ secretsAccess,
268
+ trans,
269
+ mcpServerRenderer
270
+ });
271
+ settingsWidget.title.icon = settingsIcon;
272
+ settingsWidget.title.iconClass = 'jp-ai-settings-icon';
273
+ const open = () => {
274
+ let widget = Array.from(app.shell.widgets('main')).find(w => w.id === 'jupyternaut-persona-settings');
275
+ if (!widget) {
276
+ widget = settingsWidget;
277
+ app.shell.add(widget, 'main');
278
+ }
279
+ app.shell.activateById(widget.id);
280
+ };
281
+ if (restorer) {
282
+ restorer.add(settingsWidget, settingsWidget.id);
283
+ }
284
+ app.commands.addCommand(CommandIds.openSettings, {
285
+ label: trans.__('Jupyternaut Settings'),
286
+ caption: trans.__('Configure AI providers and behavior'),
287
+ icon: settingsIcon,
288
+ iconClass: 'jp-ai-settings-icon',
289
+ execute: () => {
290
+ open();
291
+ },
292
+ describedBy: {
293
+ args: {}
294
+ }
295
+ });
296
+ if (palette) {
297
+ palette.addItem({
298
+ command: CommandIds.openSettings,
299
+ category: trans.__('AI Assistant')
300
+ });
301
+ }
302
+ }
303
+ };
304
+ /**
305
+ * Built-in completion providers plugin
306
+ */
307
+ const settingsModel = {
308
+ id: '@jupyternaut/persona:settings-model',
309
+ description: 'Provide the AI settings model',
310
+ autoStart: true,
311
+ provides: IAISettingsModel,
312
+ requires: [ISettingRegistry],
313
+ activate: (app, settingRegistry) => {
314
+ return new AISettingsModel({ settingRegistry });
315
+ }
316
+ };
317
+ /**
318
+ * Diff manager plugin
319
+ */
320
+ const diffManager = {
321
+ id: '@jupyternaut/persona:diff-manager',
322
+ description: 'Provide the diff manager for notebook cell diffs',
323
+ autoStart: true,
324
+ provides: IDiffManager,
325
+ requires: [IAISettingsModel],
326
+ activate: (app, settingsModel) => {
327
+ return new DiffManager({
328
+ commands: app.commands,
329
+ settingsModel
330
+ });
331
+ }
332
+ };
333
+ /**
334
+ * Skill registry plugin
335
+ */
336
+ const skillRegistryPlugin = {
337
+ id: '@jupyternaut/persona:skill-registry',
338
+ description: 'Provide the skill registry',
339
+ autoStart: true,
340
+ provides: ISkillRegistry,
341
+ activate: () => {
342
+ return new SkillRegistry();
343
+ }
344
+ };
345
+ const toolRegistry = {
346
+ id: '@jupyternaut/persona:tool-registry',
347
+ description: 'Provide the AI tool registry',
348
+ autoStart: true,
349
+ optional: [ISkillRegistry],
350
+ provides: IToolRegistry,
351
+ activate: (app, skillRegistry) => {
352
+ const toolRegistry = new ToolRegistry();
353
+ // Add command operation tools
354
+ const discoverCommandsTool = createDiscoverCommandsTool(app.commands);
355
+ const executeCommandTool = createExecuteCommandTool(app.commands);
356
+ toolRegistry.add('discover_commands', discoverCommandsTool);
357
+ toolRegistry.add('execute_command', executeCommandTool);
358
+ toolRegistry.add('browser_fetch', createBrowserFetchTool());
359
+ if (skillRegistry) {
360
+ toolRegistry.add('discover_skills', createDiscoverSkillsTool(skillRegistry));
361
+ toolRegistry.add('load_skill', createLoadSkillTool(skillRegistry));
362
+ }
363
+ return toolRegistry;
364
+ }
365
+ };
366
+ const completionStatus = {
367
+ id: '@jupyternaut/persona:completion-status',
368
+ description: 'The completion status displayed in the status bar',
369
+ autoStart: true,
370
+ requires: [IAISettingsModel],
371
+ optional: [IStatusBar, ITranslator],
372
+ activate: (app, settingsModel, statusBar, translator) => {
373
+ if (!statusBar) {
374
+ return;
375
+ }
376
+ const trans = (translator ?? nullTranslator).load('jupyterlite_ai');
377
+ const item = new CompletionStatusWidget({
378
+ settingsModel,
379
+ translator: trans
380
+ });
381
+ statusBar?.registerStatusItem('completionState', {
382
+ item,
383
+ align: 'right',
384
+ rank: 10
385
+ });
386
+ }
387
+ };
388
+ /**
389
+ * Skills plugin: discovers and registers agent skills from the filesystem.
390
+ */
391
+ const skillsPlugin = {
392
+ id: '@jupyternaut/persona:skills',
393
+ description: 'Discover and register agent skills',
394
+ autoStart: true,
395
+ requires: [IAISettingsModel, IDocumentManager, ISkillRegistry],
396
+ optional: [ICommandPalette, ITranslator],
397
+ activate: async (app, settingsModel, docManager, skillRegistry, palette, translator) => {
398
+ const trans = (translator ?? nullTranslator).load('jupyterlite_ai');
399
+ const validateResourcePath = (resourcePath) => {
400
+ if (resourcePath.startsWith('/')) {
401
+ return null;
402
+ }
403
+ const normalized = PathExt.normalize(resourcePath);
404
+ if (normalized.startsWith('..') || normalized === '') {
405
+ return null;
406
+ }
407
+ return normalized;
408
+ };
409
+ let currentSkillsPaths = settingsModel.config.skillsPaths;
410
+ let currentSkillDisposables = new DisposableSet();
411
+ const loadAndRegister = async () => {
412
+ const skillsPaths = settingsModel.config.skillsPaths;
413
+ const skills = await loadSkillsFromPaths(docManager.services.contents, skillsPaths);
414
+ const registrations = skills.map(skill => ({
415
+ name: skill.name,
416
+ description: skill.description,
417
+ instructions: skill.instructions,
418
+ resources: skill.resources,
419
+ loadResource: async (resource) => {
420
+ const validatedPath = validateResourcePath(resource);
421
+ if (validatedPath === null) {
422
+ return {
423
+ name: skill.name,
424
+ resource,
425
+ error: 'Invalid resource path: path traversal not allowed'
426
+ };
427
+ }
428
+ if (!skill.resources.includes(validatedPath)) {
429
+ return {
430
+ name: skill.name,
431
+ resource,
432
+ error: `Resource not found: ${resource}`
433
+ };
434
+ }
435
+ const resourcePath = `${skill.path}/${validatedPath}`;
436
+ try {
437
+ const fileModel = await docManager.services.contents.get(resourcePath, {
438
+ content: true
439
+ });
440
+ if (typeof fileModel.content !== 'string') {
441
+ return {
442
+ name: skill.name,
443
+ resource,
444
+ error: 'Resource content is not a string'
445
+ };
446
+ }
447
+ return {
448
+ name: skill.name,
449
+ resource,
450
+ content: fileModel.content
451
+ };
452
+ }
453
+ catch (error) {
454
+ return {
455
+ name: skill.name,
456
+ resource,
457
+ error: `Failed to read resource: ${error}`
458
+ };
459
+ }
460
+ }
461
+ }));
462
+ currentSkillDisposables.dispose();
463
+ currentSkillDisposables = new DisposableSet();
464
+ for (const registration of registrations) {
465
+ currentSkillDisposables.add(skillRegistry.registerSkill(registration));
466
+ }
467
+ };
468
+ app.commands.addCommand(CommandIds.refreshSkills, {
469
+ label: trans.__('Refresh Agents Skills'),
470
+ caption: trans.__('Re-scan the agents skills directory and update the registry'),
471
+ execute: async () => {
472
+ await loadAndRegister();
473
+ }
474
+ });
475
+ if (palette) {
476
+ palette.addItem({
477
+ command: CommandIds.refreshSkills,
478
+ category: trans.__('AI Assistant')
479
+ });
480
+ }
481
+ loadAndRegister().catch(error => console.warn('Failed to load skills on activation:', error));
482
+ settingsModel.stateChanged.connect(() => {
483
+ const newPaths = settingsModel.config.skillsPaths;
484
+ if (newPaths.length === currentSkillsPaths.length &&
485
+ newPaths.every((p, i) => p === currentSkillsPaths[i])) {
486
+ return;
487
+ }
488
+ currentSkillsPaths = newPaths;
489
+ loadAndRegister().catch(error => console.warn('Failed to reload skills:', error));
490
+ });
491
+ }
492
+ };
493
+ export default [
494
+ // Provider registry and builtin providers
495
+ providerRegistryPlugin,
496
+ anthropicProviderPlugin,
497
+ googleProviderPlugin,
498
+ mistralProviderPlugin,
499
+ openaiProviderPlugin,
500
+ genericProviderPlugin,
501
+ // Agent
502
+ agentManagerFactory,
503
+ completionStatus,
504
+ // Skills
505
+ skillRegistryPlugin,
506
+ skillsPlugin,
507
+ // Tools
508
+ toolRegistry,
509
+ // Persona
510
+ personaRegistry,
511
+ persona,
512
+ mentionCommandPlugin,
513
+ // Settings
514
+ settingsModel,
515
+ settingsPanelPlugin,
516
+ // Diff manager (to be removed ?)
517
+ diffManager
518
+ ];
519
+ // Export extension points for other extensions to use
520
+ export * from './tokens';
521
+ // Export helper functions
522
+ export { processAttachments } from './process-attachments';
@@ -0,0 +1,36 @@
1
+ import type { IAIConfig, IAISettingsModel, IProviderConfig } from '@jupyternaut/agent';
2
+ import { VDomModel } from '@jupyterlab/ui-components';
3
+ import { ISettingRegistry } from '@jupyterlab/settingregistry';
4
+ export declare class AISettingsModel extends VDomModel implements IAISettingsModel {
5
+ private _config;
6
+ private _settingRegistry;
7
+ private _settings;
8
+ constructor(options: AISettingsModel.IOptions);
9
+ private _initializeSettings;
10
+ private _onSettingsChanged;
11
+ private _loadFromSettings;
12
+ get config(): IAIConfig;
13
+ get providers(): IProviderConfig[];
14
+ getProvider(id: string): IProviderConfig | undefined;
15
+ getDefaultProvider(): IProviderConfig | undefined;
16
+ getCompleterProvider(): IProviderConfig | undefined;
17
+ addProvider(providerConfig: Omit<IProviderConfig, 'id'>): Promise<string>;
18
+ removeProvider(id: string): Promise<void>;
19
+ updateProvider(id: string, updates: Partial<IProviderConfig>): Promise<void>;
20
+ setActiveProvider(id: string): Promise<void>;
21
+ setActiveCompleterProvider(id: string | undefined): Promise<void>;
22
+ updateConfig(updates: Partial<IAIConfig>): Promise<void>;
23
+ /**
24
+ * Get the API key saved in the settings file for a given provider.
25
+ *
26
+ * @param id - the id of the provider.
27
+ */
28
+ getApiKey(id: string): string;
29
+ private _saveSetting;
30
+ }
31
+ export declare namespace AISettingsModel {
32
+ interface IOptions {
33
+ settingRegistry: ISettingRegistry;
34
+ }
35
+ }
36
+ //# sourceMappingURL=settings-model.d.ts.map