@jupyterlite/ai 0.7.0 → 0.8.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 (68) hide show
  1. package/lib/base-completer.d.ts +23 -1
  2. package/lib/base-completer.js +14 -1
  3. package/lib/chat-handler.d.ts +4 -6
  4. package/lib/chat-handler.js +22 -22
  5. package/lib/completion-provider.js +1 -1
  6. package/lib/default-prompts.d.ts +2 -0
  7. package/lib/default-prompts.js +31 -0
  8. package/lib/default-providers/Anthropic/completer.d.ts +4 -9
  9. package/lib/default-providers/Anthropic/completer.js +4 -13
  10. package/lib/default-providers/ChromeAI/completer.d.ts +4 -9
  11. package/lib/default-providers/ChromeAI/completer.js +4 -13
  12. package/lib/default-providers/ChromeAI/settings-schema.json +0 -3
  13. package/lib/default-providers/Gemini/completer.d.ts +12 -0
  14. package/lib/default-providers/Gemini/completer.js +48 -0
  15. package/lib/default-providers/Gemini/instructions.d.ts +2 -0
  16. package/lib/default-providers/Gemini/instructions.js +9 -0
  17. package/lib/default-providers/Gemini/settings-schema.json +64 -0
  18. package/lib/default-providers/MistralAI/completer.d.ts +10 -11
  19. package/lib/default-providers/MistralAI/completer.js +41 -50
  20. package/lib/default-providers/MistralAI/instructions.d.ts +1 -1
  21. package/lib/default-providers/MistralAI/instructions.js +2 -0
  22. package/lib/default-providers/Ollama/completer.d.ts +4 -9
  23. package/lib/default-providers/Ollama/completer.js +7 -13
  24. package/lib/default-providers/Ollama/settings-schema.json +1 -4
  25. package/lib/default-providers/OpenAI/completer.d.ts +4 -9
  26. package/lib/default-providers/OpenAI/completer.js +7 -13
  27. package/lib/default-providers/OpenAI/settings-schema.json +88 -128
  28. package/lib/default-providers/WebLLM/completer.d.ts +3 -9
  29. package/lib/default-providers/WebLLM/completer.js +4 -13
  30. package/lib/default-providers/WebLLM/settings-schema.json +1 -3
  31. package/lib/default-providers/index.js +23 -19
  32. package/lib/index.d.ts +1 -0
  33. package/lib/index.js +68 -14
  34. package/lib/provider.d.ts +39 -11
  35. package/lib/provider.js +166 -81
  36. package/lib/settings/index.d.ts +1 -0
  37. package/lib/settings/index.js +1 -0
  38. package/lib/settings/panel.d.ts +116 -8
  39. package/lib/settings/panel.js +117 -22
  40. package/lib/settings/textarea.d.ts +2 -0
  41. package/lib/settings/textarea.js +18 -0
  42. package/lib/tokens.d.ts +24 -20
  43. package/lib/tokens.js +2 -1
  44. package/package.json +10 -9
  45. package/schema/chat.json +1 -1
  46. package/schema/provider-registry.json +11 -5
  47. package/schema/system-prompts.json +22 -0
  48. package/src/base-completer.ts +39 -1
  49. package/src/chat-handler.ts +23 -25
  50. package/src/completion-provider.ts +1 -1
  51. package/src/default-prompts.ts +33 -0
  52. package/src/default-providers/Anthropic/completer.ts +5 -16
  53. package/src/default-providers/ChromeAI/completer.ts +5 -16
  54. package/src/default-providers/Gemini/completer.ts +61 -0
  55. package/src/default-providers/Gemini/instructions.ts +9 -0
  56. package/src/default-providers/MistralAI/completer.ts +47 -60
  57. package/src/default-providers/MistralAI/instructions.ts +2 -0
  58. package/src/default-providers/Ollama/completer.ts +8 -16
  59. package/src/default-providers/OpenAI/completer.ts +8 -16
  60. package/src/default-providers/WebLLM/completer.ts +5 -16
  61. package/src/default-providers/index.ts +23 -20
  62. package/src/index.ts +95 -15
  63. package/src/provider.ts +198 -94
  64. package/src/settings/index.ts +1 -0
  65. package/src/settings/panel.tsx +262 -34
  66. package/src/settings/textarea.tsx +33 -0
  67. package/src/tokens.ts +26 -22
  68. package/style/base.css +29 -0
@@ -5,7 +5,7 @@ import {
5
5
  FormComponent,
6
6
  IFormRenderer
7
7
  } from '@jupyterlab/ui-components';
8
- import { JSONExt } from '@lumino/coreutils';
8
+ import { JSONExt, ReadonlyPartialJSONObject } from '@lumino/coreutils';
9
9
  import { IChangeEvent } from '@rjsf/core';
10
10
  import type { FieldProps } from '@rjsf/utils';
11
11
  import validator from '@rjsf/validator-ajv8';
@@ -15,13 +15,16 @@ import React from 'react';
15
15
 
16
16
  import { getSecretId, SECRETS_REPLACEMENT } from '.';
17
17
  import baseSettings from './base.json';
18
- import { IAIProviderRegistry, IDict, PLUGIN_IDS } from '../tokens';
18
+ import { IAIProviderRegistry, IDict, ModelRole, PLUGIN_IDS } from '../tokens';
19
19
 
20
20
  const MD_MIME_TYPE = 'text/markdown';
21
- const STORAGE_NAME = '@jupyterlite/ai:settings';
22
21
  const INSTRUCTION_CLASS = 'jp-AISettingsInstructions';
23
22
  const ERROR_CLASS = 'jp-AISettingsError';
24
23
  const SECRETS_NAMESPACE = PLUGIN_IDS.providerRegistry;
24
+ const STORAGE_KEYS = {
25
+ chat: '@jupyterlite/ai:chat-settings',
26
+ completer: '@jupyterlite/ai:completer-settings'
27
+ };
25
28
 
26
29
  export const aiSettingsRenderer = (options: {
27
30
  providerRegistry: IAIProviderRegistry;
@@ -42,28 +45,196 @@ export const aiSettingsRenderer = (options: {
42
45
  };
43
46
  };
44
47
 
45
- export interface ISettingsFormStates {
46
- schema: JSONSchema7;
47
- instruction: HTMLElement | null;
48
- compatibilityError: string | null;
49
- isModified?: boolean;
50
- }
51
-
52
48
  const WrappedFormComponent = (props: any): JSX.Element => {
53
49
  return <FormComponent {...props} validator={validator} />;
54
50
  };
55
51
 
56
- export class AiSettings extends React.Component<
57
- FieldProps,
58
- ISettingsFormStates
59
- > {
52
+ export interface IAiSettings {
53
+ /**
54
+ * Get the local storage settings for a specific role (chat or completer).
55
+ */
56
+ getLocalStorage(role: ModelRole): IDict<any>;
57
+ /**
58
+ * Set the local storage item for a specific role (chat or completer).
59
+ * If the key is not provider (null) we assume the value should replace the whole
60
+ * local storage for this role.
61
+ */
62
+ setLocalStorageItem(role: ModelRole, key: string | null, value: any): void;
63
+ /**
64
+ * Get the settings from the registry (jupyterlab settings system) for a given role.
65
+ */
66
+ getSettingsFromRegistry(role: ModelRole): IDict<any>;
67
+ /**
68
+ * Save the settings to the setting registry.
69
+ */
70
+ saveSettingsToRegistry(role: ModelRole, settings: IDict<any>): void;
71
+ }
72
+
73
+ export class AiSettings
74
+ extends React.Component<FieldProps, AiSettings.states>
75
+ implements IAiSettings
76
+ {
60
77
  constructor(props: FieldProps) {
78
+ super(props);
79
+ this._settings = props.formContext.settings;
80
+ const uniqueProvider =
81
+ (this._settings.get('UniqueProvider').composite as boolean) ?? true;
82
+
83
+ this.state = { uniqueProvider };
84
+
85
+ this._settings.changed.connect(this._settingsChanged);
86
+ }
87
+
88
+ private _settingsChanged = () => {
89
+ const uniqueProvider =
90
+ (this._settings.get('UniqueProvider').composite as boolean) ?? true;
91
+ if (this.state.uniqueProvider === uniqueProvider) {
92
+ return;
93
+ }
94
+ if (uniqueProvider) {
95
+ // Copy chat settings to the completer settings if there should be a unique
96
+ // provider for both.
97
+ this.setLocalStorageItem('completer', null, this.getLocalStorage('chat'));
98
+ this.saveSettingsToRegistry(
99
+ 'completer',
100
+ this.getSettingsFromRegistry('chat')
101
+ );
102
+ }
103
+ this.setState({ uniqueProvider });
104
+ };
105
+
106
+ /**
107
+ * Get the local storage settings for a specific role (chat or completer).
108
+ */
109
+ getLocalStorage = (role: ModelRole): IDict<any> => {
110
+ const storageKey = STORAGE_KEYS[role];
111
+ return JSON.parse(localStorage.getItem(storageKey) ?? '{}');
112
+ };
113
+
114
+ /**
115
+ * Set the local storage item for a specific role (chat or completer).
116
+ * If the key is not provider (null) we assume the value should replace the whole
117
+ * local storage for this role.
118
+ */
119
+ setLocalStorageItem = (
120
+ role: ModelRole,
121
+ key: string | null,
122
+ value: any
123
+ ): void => {
124
+ const storageKey = STORAGE_KEYS[role];
125
+ let settings: IDict<any>;
126
+
127
+ if (key !== null) {
128
+ settings = JSON.parse(localStorage.getItem(storageKey) ?? '{}');
129
+ settings[key] = value;
130
+ } else {
131
+ settings = value;
132
+ }
133
+
134
+ localStorage.setItem(storageKey, JSON.stringify(settings));
135
+
136
+ // If both chat and completer use the same settings, only the chat settings should
137
+ // be editable for user, so we should duplicate its values to the completer
138
+ // local storage.
139
+ if (this.state.uniqueProvider && role === 'chat') {
140
+ const storageKeyCompleter = STORAGE_KEYS['completer'];
141
+ localStorage.setItem(storageKeyCompleter, JSON.stringify(settings));
142
+ }
143
+ };
144
+
145
+ /**
146
+ * Get the settings from the registry (jupyterlab settings system) for a given role.
147
+ */
148
+ getSettingsFromRegistry = (role: ModelRole): IDict<any> => {
149
+ const settings = this._settings.get('AIproviders')
150
+ .composite as ReadonlyPartialJSONObject;
151
+ return settings && Object.keys(settings).includes(role)
152
+ ? (settings[role] as IDict<any>)
153
+ : { provider: 'None' };
154
+ };
155
+
156
+ /**
157
+ * Save the settings to the setting registry.
158
+ */
159
+ saveSettingsToRegistry = (role: ModelRole, settings: IDict<any>): void => {
160
+ const fullSettings = this._settings.get('AIproviders')
161
+ .composite as IDict<any>;
162
+ fullSettings[role] = { ...settings };
163
+
164
+ // If both chat and completer use the same settings, only the chat settings should
165
+ // be editable for user, so we should duplicate its values to the completer
166
+ // settings.
167
+ if (this.state.uniqueProvider && role === 'chat') {
168
+ fullSettings['completer'] = { ...settings };
169
+ }
170
+ this._settings.set('AIproviders', { ...fullSettings }).catch(console.error);
171
+ };
172
+
173
+ render(): JSX.Element {
174
+ return (
175
+ <div>
176
+ <h3>
177
+ {this.state.uniqueProvider
178
+ ? 'Chat and completer provider'
179
+ : 'Chat provider'}
180
+ </h3>
181
+ <AiProviderSettings {...this.props} role={'chat'} aiSettings={this} />
182
+ {!this.state.uniqueProvider && (
183
+ <>
184
+ <h3>Completer provider</h3>
185
+ <AiProviderSettings
186
+ {...this.props}
187
+ role={'completer'}
188
+ aiSettings={this}
189
+ />
190
+ </>
191
+ )}
192
+ </div>
193
+ );
194
+ }
195
+
196
+ private _settings: ISettingRegistry.ISettings;
197
+ }
198
+
199
+ /**
200
+ * The AI settings component namespace.
201
+ */
202
+ namespace AiSettings {
203
+ /**
204
+ * The AI settings component states.
205
+ */
206
+ export type states = {
207
+ /**
208
+ * Whether there is only one provider for chat and completion.
209
+ */
210
+ uniqueProvider: boolean;
211
+ };
212
+ /**
213
+ * The provider names object.
214
+ */
215
+ export type providers = {
216
+ [key in ModelRole]: string;
217
+ };
218
+ /**
219
+ * The provider schemas object.
220
+ */
221
+ export type schemas = {
222
+ [key in ModelRole]: JSONSchema7;
223
+ };
224
+ }
225
+
226
+ export class AiProviderSettings extends React.Component<
227
+ AiProviderSettings.props,
228
+ AiProviderSettings.states
229
+ > {
230
+ constructor(props: AiProviderSettings.props) {
61
231
  super(props);
62
232
  if (!props.formContext.providerRegistry) {
63
233
  throw new Error(
64
234
  'The provider registry is needed to enable the jupyterlite-ai settings panel'
65
235
  );
66
236
  }
237
+ this._role = props.role;
67
238
  this._providerRegistry = props.formContext.providerRegistry;
68
239
  this._rmRegistry = props.formContext.rmRegistry ?? null;
69
240
  this._secretsManager = props.formContext.secretsManager ?? null;
@@ -87,10 +258,13 @@ export class AiSettings extends React.Component<
87
258
 
88
259
  // Check if there is saved values in local storage, otherwise use the settings from
89
260
  // the setting registry (leads to default if there are no user settings).
90
- const storageSettings = localStorage.getItem(STORAGE_NAME);
261
+ const storageKey = STORAGE_KEYS[this._role];
262
+ const storageSettings = localStorage.getItem(storageKey);
91
263
  if (storageSettings === null) {
92
- const labSettings = this._settings.get('AIprovider').composite;
93
- if (labSettings && Object.keys(labSettings).includes('provider')) {
264
+ const labSettings = this.props.aiSettings.getSettingsFromRegistry(
265
+ this._role
266
+ );
267
+ if (Object.keys(labSettings).includes('provider')) {
94
268
  // Get the provider name.
95
269
  const provider = Object.entries(labSettings).find(
96
270
  v => v[0] === 'provider'
@@ -100,7 +274,7 @@ export class AiSettings extends React.Component<
100
274
  _current: provider
101
275
  };
102
276
  settings[provider] = labSettings;
103
- localStorage.setItem(STORAGE_NAME, JSON.stringify(settings));
277
+ this.props.aiSettings.setLocalStorageItem(this._role, null, settings);
104
278
  }
105
279
  }
106
280
 
@@ -135,6 +309,10 @@ export class AiSettings extends React.Component<
135
309
  this._settings.changed.connect(this._settingsChanged);
136
310
  }
137
311
 
312
+ componentDidMount(): void {
313
+ this.componentDidUpdate();
314
+ }
315
+
138
316
  async componentDidUpdate(): Promise<void> {
139
317
  if (!this._secretsManager || !this._useSecretsManager) {
140
318
  return;
@@ -175,7 +353,7 @@ export class AiSettings extends React.Component<
175
353
  * Get the current provider from the local storage.
176
354
  */
177
355
  getCurrentProvider(): string {
178
- const settings = JSON.parse(localStorage.getItem(STORAGE_NAME) || '{}');
356
+ const settings = this.props.aiSettings.getLocalStorage(this._role);
179
357
  return settings['_current'] ?? 'None';
180
358
  }
181
359
 
@@ -183,16 +361,18 @@ export class AiSettings extends React.Component<
183
361
  * Save the current provider to the local storage.
184
362
  */
185
363
  saveCurrentProvider(): void {
186
- const settings = JSON.parse(localStorage.getItem(STORAGE_NAME) || '{}');
187
- settings['_current'] = this._provider;
188
- localStorage.setItem(STORAGE_NAME, JSON.stringify(settings));
364
+ this.props.aiSettings.setLocalStorageItem(
365
+ this._role,
366
+ '_current',
367
+ this._provider
368
+ );
189
369
  }
190
370
 
191
371
  /**
192
- * Get settings from local storage for a given provider.
372
+ * Get settings from local storage for the current provider provider.
193
373
  */
194
374
  getSettingsFromLocalStorage(): IDict<any> {
195
- const settings = JSON.parse(localStorage.getItem(STORAGE_NAME) || '{}');
375
+ const settings = this.props.aiSettings.getLocalStorage(this._role);
196
376
  return settings[this._provider] ?? { provider: this._provider };
197
377
  }
198
378
 
@@ -201,13 +381,15 @@ export class AiSettings extends React.Component<
201
381
  */
202
382
  saveSettingsToLocalStorage() {
203
383
  const currentSettings = { ...this._currentSettings };
204
- const settings = JSON.parse(localStorage.getItem(STORAGE_NAME) ?? '{}');
205
384
  // Do not save secrets in local storage if using the secrets manager.
206
385
  if (this._useSecretsManager) {
207
386
  this._secretFields.forEach(field => delete currentSettings[field]);
208
387
  }
209
- settings[this._provider] = currentSettings;
210
- localStorage.setItem(STORAGE_NAME, JSON.stringify(settings));
388
+ this.props.aiSettings.setLocalStorageItem(
389
+ this._role,
390
+ this._provider,
391
+ currentSettings
392
+ );
211
393
  }
212
394
 
213
395
  /**
@@ -220,9 +402,11 @@ export class AiSettings extends React.Component<
220
402
  sanitizedSettings[field] = SECRETS_REPLACEMENT;
221
403
  });
222
404
  }
223
- this._settings
224
- .set('AIprovider', { provider: this._provider, ...sanitizedSettings })
225
- .catch(console.error);
405
+
406
+ this.props.aiSettings.saveSettingsToRegistry(this._role, {
407
+ provider: this._provider,
408
+ ...sanitizedSettings
409
+ });
226
410
  }
227
411
 
228
412
  /**
@@ -265,7 +449,7 @@ export class AiSettings extends React.Component<
265
449
  this._secretsManager.detachAll(Private.getToken(), SECRETS_NAMESPACE);
266
450
  } else {
267
451
  // Remove all the keys stored locally.
268
- const settings = JSON.parse(localStorage.getItem(STORAGE_NAME) || '{}');
452
+ const settings = this.props.aiSettings.getLocalStorage(this._role);
269
453
  Object.keys(settings).forEach(provider => {
270
454
  Object.keys(settings[provider])
271
455
  .filter(key => key.toLowerCase().includes('key'))
@@ -273,7 +457,7 @@ export class AiSettings extends React.Component<
273
457
  delete settings[provider][key];
274
458
  });
275
459
  });
276
- localStorage.setItem(STORAGE_NAME, JSON.stringify(settings));
460
+ this.props.aiSettings.setLocalStorageItem(this._role, null, settings);
277
461
  }
278
462
  this._updateSchema();
279
463
  this.saveSettingsToLocalStorage();
@@ -297,7 +481,7 @@ export class AiSettings extends React.Component<
297
481
  if (key.toLowerCase().includes('key')) {
298
482
  this._secretFields.push(key);
299
483
 
300
- // If the secrets manager is not used, do not show the secrets fields.
484
+ // If the secrets manager is not used, show the secrets fields.
301
485
  // If the secrets manager is used, check if the fields should be visible.
302
486
  const showSecretFields =
303
487
  !this._useSecretsManager ||
@@ -467,6 +651,7 @@ export class AiSettings extends React.Component<
467
651
  formData={{ provider: this._provider }}
468
652
  schema={this._providerSchema}
469
653
  onChange={this._onProviderChanged}
654
+ idPrefix={`jp-SettingsEditor-${PLUGIN_IDS.providerRegistry}-${this._role}`}
470
655
  />
471
656
  {this.state.compatibilityError !== null && (
472
657
  <div className={ERROR_CLASS}>
@@ -499,7 +684,7 @@ export class AiSettings extends React.Component<
499
684
  schema={this.state.schema}
500
685
  onChange={this._onFormChanged}
501
686
  uiSchema={this._uiSchema}
502
- idPrefix={`jp-SettingsEditor-${PLUGIN_IDS.providerRegistry}`}
687
+ idPrefix={`jp-SettingsEditor-${PLUGIN_IDS.providerRegistry}-${this._role}`}
503
688
  formContext={{
504
689
  ...this.props.formContext,
505
690
  defaultFormData: this._defaultFormData
@@ -509,6 +694,7 @@ export class AiSettings extends React.Component<
509
694
  );
510
695
  }
511
696
 
697
+ private _role: ModelRole;
512
698
  private _providerRegistry: IAIProviderRegistry;
513
699
  private _provider: string;
514
700
  private _providerSchema: JSONSchema7;
@@ -523,6 +709,48 @@ export class AiSettings extends React.Component<
523
709
  private _defaultFormData: IDict<any> = {};
524
710
  }
525
711
 
712
+ /**
713
+ * The AI provider settings component namespace.
714
+ */
715
+ export namespace AiProviderSettings {
716
+ /**
717
+ * The AI provider settings component props.
718
+ */
719
+ export type props = FieldProps & {
720
+ /**
721
+ * Why this model is used for (chat or completion).
722
+ */
723
+ role: ModelRole;
724
+ /**
725
+ * The parent component which should handle:
726
+ * - the get/set functions for local storage
727
+ * - save settings using jupyter settings system
728
+ */
729
+ aiSettings: IAiSettings;
730
+ };
731
+ /**
732
+ * The AI provider settings component states.
733
+ */
734
+ export type states = {
735
+ /**
736
+ * The schema of the settings.
737
+ */
738
+ schema: JSONSchema7;
739
+ /**
740
+ * The instructions for this provider.
741
+ */
742
+ instruction: HTMLElement | null;
743
+ /**
744
+ * An error if the model in not compatible with the current environment.
745
+ */
746
+ compatibilityError: string | null;
747
+ /**
748
+ * Whether the settings are modified from default or not.
749
+ */
750
+ isModified?: boolean;
751
+ };
752
+ }
753
+
526
754
  namespace Private {
527
755
  /**
528
756
  * The token to use with the secrets manager.
@@ -0,0 +1,33 @@
1
+ import { ISettingRegistry } from '@jupyterlab/settingregistry';
2
+ import { IFormRenderer } from '@jupyterlab/ui-components';
3
+ import { FieldProps } from '@rjsf/utils';
4
+ import React, { useState } from 'react';
5
+
6
+ const TEXTAREA_CLASS = 'jp-AISettingsTextArea';
7
+
8
+ export const textArea: IFormRenderer = {
9
+ fieldRenderer: (props: FieldProps) => {
10
+ const settings: ISettingRegistry.ISettings = props.formContext.settings;
11
+ const schema = settings.schema.properties?.[props.name];
12
+ const [formData, setFormData] = useState<string>(props.formData);
13
+ settings.changed.connect(() => {
14
+ setFormData(settings.get(props.name).composite as string);
15
+ });
16
+ const onChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
17
+ settings.set(props.name, event.target.value);
18
+ };
19
+
20
+ return (
21
+ <>
22
+ {schema?.title && (
23
+ <h3 className="jp-FormGroup-fieldLabel jp-FormGroup-contentItem">
24
+ {schema.title}
25
+ </h3>
26
+ )}
27
+ <textarea className={TEXTAREA_CLASS} onChange={onChange}>
28
+ {formData}
29
+ </textarea>
30
+ </>
31
+ );
32
+ }
33
+ };
package/src/tokens.ts CHANGED
@@ -11,9 +11,12 @@ export const PLUGIN_IDS = {
11
11
  chatCommandRegistry: '@jupyterlite/ai:autocompletion-registry',
12
12
  completer: '@jupyterlite/ai:completer',
13
13
  providerRegistry: '@jupyterlite/ai:provider-registry',
14
- settingsConnector: '@jupyterlite/ai:settings-connector'
14
+ settingsConnector: '@jupyterlite/ai:settings-connector',
15
+ systemPrompts: '@jupyterlite/ai:system-prompts'
15
16
  };
16
17
 
18
+ export type ModelRole = 'chat' | 'completer';
19
+
17
20
  export interface IDict<T = any> {
18
21
  [key: string]: T;
19
22
  }
@@ -33,7 +36,7 @@ export interface IAIProvider {
33
36
  /**
34
37
  * The chat model class to use.
35
38
  */
36
- chatModel?: IType<BaseChatModel>;
39
+ chat?: IType<BaseChatModel>;
37
40
  /**
38
41
  * The completer class to use.
39
42
  */
@@ -83,15 +86,23 @@ export interface IAIProviderRegistry {
83
86
  /**
84
87
  * Get the current provider name.
85
88
  */
86
- currentName: string;
89
+ currentName(role: ModelRole): string;
87
90
  /**
88
91
  * Get the current completer of the completion provider.
89
92
  */
90
93
  currentCompleter: AICompleter | null;
94
+ /**
95
+ * Getter/setter for the completer system prompt.
96
+ */
97
+ completerSystemPrompt: string;
91
98
  /**
92
99
  * Get the current llm chat model.
93
100
  */
94
101
  currentChatModel: AIChatModel | null;
102
+ /**
103
+ * Getter/setter for the chat system prompt.
104
+ */
105
+ chatSystemPrompt: string;
95
106
  /**
96
107
  * Get the settings schema of a given provider.
97
108
  */
@@ -111,16 +122,23 @@ export interface IAIProviderRegistry {
111
122
  */
112
123
  formatErrorMessage(error: any): string;
113
124
  /**
114
- * Set the providers (chat model and completer).
115
- * Creates the providers if the name has changed, otherwise only updates their config.
125
+ * Set the completer provider.
126
+ * Creates the provider if the name has changed, otherwise only updates its config.
116
127
  *
117
- * @param options - an object with the name and the settings of the provider to use.
128
+ * @param options - An object with the name and the settings of the provider to use.
118
129
  */
119
- setProvider(options: ISetProviderOptions): void;
130
+ setCompleterProvider(settings: ReadonlyPartialJSONObject): void;
131
+ /**
132
+ * Set the chat provider.
133
+ * Creates the provider if the name has changed, otherwise only updates its config.
134
+ *
135
+ * @param options - An object with the name and the settings of the provider to use.
136
+ */
137
+ setChatProvider(settings: ReadonlyPartialJSONObject): void;
120
138
  /**
121
139
  * A signal emitting when the provider or its settings has changed.
122
140
  */
123
- readonly providerChanged: ISignal<IAIProviderRegistry, void>;
141
+ readonly providerChanged: ISignal<IAIProviderRegistry, ModelRole>;
124
142
  /**
125
143
  * Get the current chat error;
126
144
  */
@@ -131,20 +149,6 @@ export interface IAIProviderRegistry {
131
149
  readonly completerError: string;
132
150
  }
133
151
 
134
- /**
135
- * The set provider options.
136
- */
137
- export interface ISetProviderOptions {
138
- /**
139
- * The name of the provider.
140
- */
141
- name: string;
142
- /**
143
- * The settings of the provider.
144
- */
145
- settings: ReadonlyPartialJSONObject;
146
- }
147
-
148
152
  /**
149
153
  * The provider registry token.
150
154
  */
package/style/base.css CHANGED
@@ -14,3 +14,32 @@
14
14
  color: var(--jp-error-color1);
15
15
  font-size: var(--jp-content-font-size1);
16
16
  }
17
+
18
+ .jp-AISettingsTextArea {
19
+ min-width: 400px;
20
+ min-height: 300px;
21
+ }
22
+
23
+ .jp-chat-welcome-message {
24
+ text-align: center;
25
+ max-width: 350px;
26
+ margin: 0 auto;
27
+ }
28
+
29
+ .jp-chat-welcome-message button[data-commandLinker-command] {
30
+ background: var(--jp-layout-color2);
31
+ border: 1px solid var(--jp-border-color1);
32
+ color: var(--jp-ui-font-color1);
33
+ border-radius: var(--jp-border-radius);
34
+ cursor: pointer;
35
+ font-size: inherit;
36
+ font-family: inherit;
37
+ padding: 2px 6px;
38
+ transition: all 0.2s ease;
39
+ }
40
+
41
+ .jp-chat-welcome-message button[data-commandLinker-command]:hover {
42
+ background: var(--jp-layout-color3);
43
+ border-color: var(--jp-brand-color1);
44
+ color: var(--jp-brand-color1);
45
+ }