Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cd80cd2

Browse files
committedMar 13, 2025·
Add an option to use or not the secrets manager in settings
1 parent 0597746 commit cd80cd2

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed
 

‎schema/provider-registry.json

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
"jupyter.lab.setting-icon-label": "JupyterLite AI Chat",
66
"type": "object",
77
"properties": {
8+
"UseSecretsManager": {
9+
"type": "boolean",
10+
"title": "Use secrets manager",
11+
"description": "Whether to use or not the secrets manager. If not, secrets will be stored in the browser (local storage)",
12+
"default": true
13+
},
814
"AIprovider": {
915
"type": "object",
1016
"title": "AI provider",

‎src/settings/panel.tsx

+39-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ export class AiSettings extends React.Component<
5656
this._secretsManager = props.formContext.secretsManager ?? null;
5757
this._settings = props.formContext.settings;
5858

59+
this._useSecretsManager =
60+
(this._settings.get('UseSecretsManager').composite as boolean) ?? true;
61+
5962
// Initialize the providers schema.
6063
const providerSchema = JSONExt.deepCopy(baseSettings) as any;
6164
providerSchema.properties.provider = {
@@ -100,10 +103,18 @@ export class AiSettings extends React.Component<
100103
this._settings
101104
.set('AIprovider', this._currentSettings)
102105
.catch(console.error);
106+
107+
this._settings.changed.connect(() => {
108+
const useSecretsManager =
109+
(this._settings.get('UseSecretsManager').composite as boolean) ?? true;
110+
if (useSecretsManager !== this._useSecretsManager) {
111+
this.updateUseSecretsManager(useSecretsManager);
112+
}
113+
});
103114
}
104115

105116
async componentDidUpdate(): Promise<void> {
106-
if (!this._secretsManager) {
117+
if (!this._secretsManager || !this._useSecretsManager) {
107118
return;
108119
}
109120
// Attach the password inputs to the secrets manager only if they have changed.
@@ -112,7 +123,7 @@ export class AiSettings extends React.Component<
112123
return;
113124
}
114125

115-
await this._secretsManager?.detachAll(SECRETS_NAMESPACE);
126+
await this._secretsManager.detachAll(SECRETS_NAMESPACE);
116127
this._formInputs = [...inputs];
117128
this._unsavedFields = [];
118129
for (let i = 0; i < inputs.length; i++) {
@@ -168,6 +179,31 @@ export class AiSettings extends React.Component<
168179
localStorage.setItem(STORAGE_NAME, JSON.stringify(settings));
169180
}
170181

182+
private updateUseSecretsManager = (value: boolean) => {
183+
this._useSecretsManager = value;
184+
if (!value) {
185+
// Detach all the password inputs attached to the secrets manager, and save the
186+
// current settings to the local storage to save the password.
187+
this._secretsManager?.detachAll(SECRETS_NAMESPACE);
188+
this._formInputs = [];
189+
this._unsavedFields = [];
190+
this.saveSettings(this._currentSettings);
191+
} else {
192+
// Remove all the keys stored locally and attach the password inputs to the
193+
// secrets manager.
194+
const settings = JSON.parse(localStorage.getItem(STORAGE_NAME) || '{}');
195+
Object.keys(settings).forEach(provider => {
196+
Object.keys(settings[provider])
197+
.filter(key => key.toLowerCase().includes('key'))
198+
.forEach(key => {
199+
delete settings[provider][key];
200+
});
201+
});
202+
localStorage.setItem(STORAGE_NAME, JSON.stringify(settings));
203+
this.componentDidUpdate();
204+
}
205+
};
206+
171207
/**
172208
* Update the UI schema of the form.
173209
* Currently use to hide API keys.
@@ -298,6 +334,7 @@ export class AiSettings extends React.Component<
298334
private _providerRegistry: IAIProviderRegistry;
299335
private _provider: string;
300336
private _providerSchema: JSONSchema7;
337+
private _useSecretsManager: boolean;
301338
private _rmRegistry: IRenderMimeRegistry | null;
302339
private _secretsManager: ISecretsManager | null;
303340
private _currentSettings: IDict<any> = { provider: 'None' };

0 commit comments

Comments
 (0)
Please sign in to comment.