@jupyterlite/ai 0.6.2 → 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.
- package/README.md +1 -1
- package/lib/base-completer.d.ts +22 -5
- package/lib/base-completer.js +14 -1
- package/lib/chat-handler.d.ts +23 -11
- package/lib/chat-handler.js +66 -45
- package/lib/completion-provider.d.ts +2 -2
- package/lib/completion-provider.js +5 -4
- package/lib/components/stop-button.d.ts +0 -1
- package/lib/default-prompts.d.ts +2 -0
- package/lib/default-prompts.js +31 -0
- package/lib/default-providers/Anthropic/completer.d.ts +4 -11
- package/lib/default-providers/Anthropic/completer.js +5 -16
- package/lib/default-providers/ChromeAI/completer.d.ts +4 -11
- package/lib/default-providers/ChromeAI/completer.js +5 -16
- package/lib/default-providers/ChromeAI/instructions.d.ts +4 -0
- package/lib/default-providers/ChromeAI/instructions.js +18 -0
- package/lib/default-providers/ChromeAI/settings-schema.json +0 -3
- package/lib/default-providers/Gemini/completer.d.ts +12 -0
- package/lib/default-providers/Gemini/completer.js +48 -0
- package/lib/default-providers/Gemini/instructions.d.ts +2 -0
- package/lib/default-providers/Gemini/instructions.js +9 -0
- package/lib/default-providers/Gemini/settings-schema.json +64 -0
- package/lib/default-providers/MistralAI/completer.d.ts +10 -13
- package/lib/default-providers/MistralAI/completer.js +42 -52
- package/lib/default-providers/MistralAI/instructions.d.ts +1 -1
- package/lib/default-providers/MistralAI/instructions.js +2 -0
- package/lib/default-providers/Ollama/completer.d.ts +12 -0
- package/lib/default-providers/Ollama/completer.js +43 -0
- package/lib/default-providers/Ollama/instructions.d.ts +2 -0
- package/lib/default-providers/Ollama/instructions.js +70 -0
- package/lib/default-providers/Ollama/settings-schema.json +143 -0
- package/lib/default-providers/OpenAI/completer.d.ts +4 -11
- package/lib/default-providers/OpenAI/completer.js +8 -16
- package/lib/default-providers/OpenAI/settings-schema.json +88 -128
- package/lib/default-providers/WebLLM/completer.d.ts +21 -0
- package/lib/default-providers/WebLLM/completer.js +127 -0
- package/lib/default-providers/WebLLM/instructions.d.ts +6 -0
- package/lib/default-providers/WebLLM/instructions.js +32 -0
- package/lib/default-providers/WebLLM/settings-schema.json +19 -0
- package/lib/default-providers/index.js +127 -8
- package/lib/index.d.ts +3 -2
- package/lib/index.js +80 -36
- package/lib/provider.d.ts +48 -22
- package/lib/provider.js +254 -101
- package/lib/settings/index.d.ts +1 -1
- package/lib/settings/index.js +1 -1
- package/lib/settings/panel.d.ts +151 -14
- package/lib/settings/panel.js +334 -145
- package/lib/settings/textarea.d.ts +2 -0
- package/lib/settings/textarea.js +18 -0
- package/lib/tokens.d.ts +45 -22
- package/lib/tokens.js +2 -1
- package/lib/types/ai-model.d.ts +24 -0
- package/lib/types/ai-model.js +5 -0
- package/package.json +19 -15
- package/schema/chat.json +1 -1
- package/schema/provider-registry.json +8 -8
- package/schema/system-prompts.json +22 -0
- package/src/base-completer.ts +38 -6
- package/src/chat-handler.ts +62 -31
- package/src/completion-provider.ts +3 -3
- package/src/default-prompts.ts +33 -0
- package/src/default-providers/Anthropic/completer.ts +5 -21
- package/src/default-providers/ChromeAI/completer.ts +5 -21
- package/src/default-providers/ChromeAI/instructions.ts +21 -0
- package/src/default-providers/Gemini/completer.ts +61 -0
- package/src/default-providers/Gemini/instructions.ts +9 -0
- package/src/default-providers/MistralAI/completer.ts +47 -65
- package/src/default-providers/MistralAI/instructions.ts +2 -0
- package/src/default-providers/Ollama/completer.ts +54 -0
- package/src/default-providers/Ollama/instructions.ts +70 -0
- package/src/default-providers/OpenAI/completer.ts +8 -21
- package/src/default-providers/WebLLM/completer.ts +151 -0
- package/src/default-providers/WebLLM/instructions.ts +33 -0
- package/src/default-providers/index.ts +158 -18
- package/src/index.ts +108 -40
- package/src/provider.ts +300 -109
- package/src/settings/index.ts +1 -1
- package/src/settings/panel.tsx +463 -101
- package/src/settings/textarea.tsx +33 -0
- package/src/tokens.ts +49 -24
- package/src/types/ai-model.ts +37 -0
- package/src/types/service-worker.d.ts +6 -0
- package/style/base.css +34 -0
- package/lib/settings/settings-connector.d.ts +0 -31
- package/lib/settings/settings-connector.js +0 -61
- package/src/settings/settings-connector.ts +0 -88
|
@@ -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
|
@@ -4,15 +4,19 @@ import { ISignal } from '@lumino/signaling';
|
|
|
4
4
|
import { JSONSchema7 } from 'json-schema';
|
|
5
5
|
|
|
6
6
|
import { IBaseCompleter } from './base-completer';
|
|
7
|
+
import { AIChatModel, AICompleter } from './types/ai-model';
|
|
7
8
|
|
|
8
9
|
export const PLUGIN_IDS = {
|
|
9
10
|
chat: '@jupyterlite/ai:chat',
|
|
10
11
|
chatCommandRegistry: '@jupyterlite/ai:autocompletion-registry',
|
|
11
12
|
completer: '@jupyterlite/ai:completer',
|
|
12
13
|
providerRegistry: '@jupyterlite/ai:provider-registry',
|
|
13
|
-
settingsConnector: '@jupyterlite/ai:settings-connector'
|
|
14
|
+
settingsConnector: '@jupyterlite/ai:settings-connector',
|
|
15
|
+
systemPrompts: '@jupyterlite/ai:system-prompts'
|
|
14
16
|
};
|
|
15
17
|
|
|
18
|
+
export type ModelRole = 'chat' | 'completer';
|
|
19
|
+
|
|
16
20
|
export interface IDict<T = any> {
|
|
17
21
|
[key: string]: T;
|
|
18
22
|
}
|
|
@@ -32,7 +36,7 @@ export interface IAIProvider {
|
|
|
32
36
|
/**
|
|
33
37
|
* The chat model class to use.
|
|
34
38
|
*/
|
|
35
|
-
|
|
39
|
+
chat?: IType<BaseChatModel>;
|
|
36
40
|
/**
|
|
37
41
|
* The completer class to use.
|
|
38
42
|
*/
|
|
@@ -51,6 +55,20 @@ export interface IAIProvider {
|
|
|
51
55
|
* Default to `(error) => error.message`.
|
|
52
56
|
*/
|
|
53
57
|
errorMessage?: (error: any) => string;
|
|
58
|
+
/**
|
|
59
|
+
* Compatibility check function, to determine if the provider is compatible with the
|
|
60
|
+
* current environment.
|
|
61
|
+
*/
|
|
62
|
+
compatibilityCheck?: () => Promise<string | null>;
|
|
63
|
+
/**
|
|
64
|
+
* Whether to expose or not the chat model.
|
|
65
|
+
*
|
|
66
|
+
* ### CAUTION
|
|
67
|
+
* This flag will expose the whole chat model API, which may contain private keys.
|
|
68
|
+
* Be sure to use it with a model that does not expose sensitive information in the
|
|
69
|
+
* API.
|
|
70
|
+
*/
|
|
71
|
+
exposeChatModel?: boolean;
|
|
54
72
|
}
|
|
55
73
|
|
|
56
74
|
/**
|
|
@@ -68,15 +86,23 @@ export interface IAIProviderRegistry {
|
|
|
68
86
|
/**
|
|
69
87
|
* Get the current provider name.
|
|
70
88
|
*/
|
|
71
|
-
currentName: string;
|
|
89
|
+
currentName(role: ModelRole): string;
|
|
72
90
|
/**
|
|
73
91
|
* Get the current completer of the completion provider.
|
|
74
92
|
*/
|
|
75
|
-
currentCompleter:
|
|
93
|
+
currentCompleter: AICompleter | null;
|
|
94
|
+
/**
|
|
95
|
+
* Getter/setter for the completer system prompt.
|
|
96
|
+
*/
|
|
97
|
+
completerSystemPrompt: string;
|
|
76
98
|
/**
|
|
77
99
|
* Get the current llm chat model.
|
|
78
100
|
*/
|
|
79
|
-
currentChatModel:
|
|
101
|
+
currentChatModel: AIChatModel | null;
|
|
102
|
+
/**
|
|
103
|
+
* Getter/setter for the chat system prompt.
|
|
104
|
+
*/
|
|
105
|
+
chatSystemPrompt: string;
|
|
80
106
|
/**
|
|
81
107
|
* Get the settings schema of a given provider.
|
|
82
108
|
*/
|
|
@@ -85,21 +111,34 @@ export interface IAIProviderRegistry {
|
|
|
85
111
|
* Get the instructions of a given provider.
|
|
86
112
|
*/
|
|
87
113
|
getInstructions(provider: string): string | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Get the compatibility check function of a given provider.
|
|
116
|
+
*/
|
|
117
|
+
getCompatibilityCheck(
|
|
118
|
+
provider: string
|
|
119
|
+
): (() => Promise<string | null>) | undefined;
|
|
88
120
|
/**
|
|
89
121
|
* Format an error message from the current provider.
|
|
90
122
|
*/
|
|
91
123
|
formatErrorMessage(error: any): string;
|
|
92
124
|
/**
|
|
93
|
-
* Set the
|
|
94
|
-
* Creates the
|
|
125
|
+
* Set the completer provider.
|
|
126
|
+
* Creates the provider if the name has changed, otherwise only updates its config.
|
|
95
127
|
*
|
|
96
|
-
* @param options -
|
|
128
|
+
* @param options - An object with the name and the settings of the provider to use.
|
|
97
129
|
*/
|
|
98
|
-
|
|
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;
|
|
99
138
|
/**
|
|
100
139
|
* A signal emitting when the provider or its settings has changed.
|
|
101
140
|
*/
|
|
102
|
-
readonly providerChanged: ISignal<IAIProviderRegistry,
|
|
141
|
+
readonly providerChanged: ISignal<IAIProviderRegistry, ModelRole>;
|
|
103
142
|
/**
|
|
104
143
|
* Get the current chat error;
|
|
105
144
|
*/
|
|
@@ -110,20 +149,6 @@ export interface IAIProviderRegistry {
|
|
|
110
149
|
readonly completerError: string;
|
|
111
150
|
}
|
|
112
151
|
|
|
113
|
-
/**
|
|
114
|
-
* The set provider options.
|
|
115
|
-
*/
|
|
116
|
-
export interface ISetProviderOptions {
|
|
117
|
-
/**
|
|
118
|
-
* The name of the provider.
|
|
119
|
-
*/
|
|
120
|
-
name: string;
|
|
121
|
-
/**
|
|
122
|
-
* The settings of the provider.
|
|
123
|
-
*/
|
|
124
|
-
settings: ReadonlyPartialJSONObject;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
152
|
/**
|
|
128
153
|
* The provider registry token.
|
|
129
154
|
*/
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
CompletionHandler,
|
|
8
|
+
IInlineCompletionContext
|
|
9
|
+
} from '@jupyterlab/completer';
|
|
10
|
+
import { IterableReadableStream } from '@langchain/core/utils/stream';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The reduced AI chat model interface.
|
|
14
|
+
*/
|
|
15
|
+
export type AIChatModel = {
|
|
16
|
+
/**
|
|
17
|
+
* The stream function of the chat model.
|
|
18
|
+
*/
|
|
19
|
+
stream: (input: any, options?: any) => Promise<IterableReadableStream<any>>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The reduced AI completer interface.
|
|
24
|
+
*/
|
|
25
|
+
export type AICompleter = {
|
|
26
|
+
/**
|
|
27
|
+
* The fetch function of the completer.
|
|
28
|
+
*/
|
|
29
|
+
fetch: (
|
|
30
|
+
request: CompletionHandler.IRequest,
|
|
31
|
+
context: IInlineCompletionContext
|
|
32
|
+
) => Promise<any>;
|
|
33
|
+
/**
|
|
34
|
+
* The optional request completion function of the completer.
|
|
35
|
+
*/
|
|
36
|
+
requestCompletion?: () => void;
|
|
37
|
+
};
|
package/style/base.css
CHANGED
|
@@ -9,3 +9,37 @@
|
|
|
9
9
|
.jp-AISettingsInstructions {
|
|
10
10
|
font-size: var(--jp-content-font-size1);
|
|
11
11
|
}
|
|
12
|
+
|
|
13
|
+
.jp-AISettingsError {
|
|
14
|
+
color: var(--jp-error-color1);
|
|
15
|
+
font-size: var(--jp-content-font-size1);
|
|
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
|
+
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { ISettingConnector, ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
2
|
-
import { DataConnector, IDataConnector } from '@jupyterlab/statedb';
|
|
3
|
-
/**
|
|
4
|
-
* A data connector for fetching settings.
|
|
5
|
-
*
|
|
6
|
-
* #### Notes
|
|
7
|
-
* This connector adds a query parameter to the base services setting manager.
|
|
8
|
-
*/
|
|
9
|
-
export declare class SettingConnector extends DataConnector<ISettingRegistry.IPlugin, string> implements ISettingConnector {
|
|
10
|
-
constructor(connector: IDataConnector<ISettingRegistry.IPlugin, string>);
|
|
11
|
-
set doNotSave(fields: string[]);
|
|
12
|
-
/**
|
|
13
|
-
* Fetch settings for a plugin.
|
|
14
|
-
* @param id - The plugin ID
|
|
15
|
-
*
|
|
16
|
-
* #### Notes
|
|
17
|
-
* The REST API requests are throttled at one request per plugin per 100ms.
|
|
18
|
-
*/
|
|
19
|
-
fetch(id: string): Promise<ISettingRegistry.IPlugin | undefined>;
|
|
20
|
-
list(query: 'ids'): Promise<{
|
|
21
|
-
ids: string[];
|
|
22
|
-
}>;
|
|
23
|
-
list(query: 'active' | 'all'): Promise<{
|
|
24
|
-
ids: string[];
|
|
25
|
-
values: ISettingRegistry.IPlugin[];
|
|
26
|
-
}>;
|
|
27
|
-
save(id: string, raw: string): Promise<void>;
|
|
28
|
-
private _connector;
|
|
29
|
-
private _doNotSave;
|
|
30
|
-
private _throttlers;
|
|
31
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { PageConfig } from '@jupyterlab/coreutils';
|
|
2
|
-
import { DataConnector } from '@jupyterlab/statedb';
|
|
3
|
-
import { Throttler } from '@lumino/polling';
|
|
4
|
-
import * as json5 from 'json5';
|
|
5
|
-
import { SECRETS_REPLACEMENT } from '.';
|
|
6
|
-
/**
|
|
7
|
-
* A data connector for fetching settings.
|
|
8
|
-
*
|
|
9
|
-
* #### Notes
|
|
10
|
-
* This connector adds a query parameter to the base services setting manager.
|
|
11
|
-
*/
|
|
12
|
-
export class SettingConnector extends DataConnector {
|
|
13
|
-
constructor(connector) {
|
|
14
|
-
super();
|
|
15
|
-
this._doNotSave = [];
|
|
16
|
-
this._throttlers = Object.create(null);
|
|
17
|
-
this._connector = connector;
|
|
18
|
-
}
|
|
19
|
-
set doNotSave(fields) {
|
|
20
|
-
this._doNotSave = [...fields];
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Fetch settings for a plugin.
|
|
24
|
-
* @param id - The plugin ID
|
|
25
|
-
*
|
|
26
|
-
* #### Notes
|
|
27
|
-
* The REST API requests are throttled at one request per plugin per 100ms.
|
|
28
|
-
*/
|
|
29
|
-
fetch(id) {
|
|
30
|
-
const throttlers = this._throttlers;
|
|
31
|
-
if (!(id in throttlers)) {
|
|
32
|
-
throttlers[id] = new Throttler(() => this._connector.fetch(id), 100);
|
|
33
|
-
}
|
|
34
|
-
return throttlers[id].invoke();
|
|
35
|
-
}
|
|
36
|
-
async list(query = 'all') {
|
|
37
|
-
const { isDisabled } = PageConfig.Extension;
|
|
38
|
-
const { ids, values } = await this._connector.list(query === 'ids' ? 'ids' : undefined);
|
|
39
|
-
if (query === 'all') {
|
|
40
|
-
return { ids, values };
|
|
41
|
-
}
|
|
42
|
-
if (query === 'ids') {
|
|
43
|
-
return { ids };
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
ids: ids.filter(id => !isDisabled(id)),
|
|
47
|
-
values: values.filter(({ id }) => !isDisabled(id))
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
async save(id, raw) {
|
|
51
|
-
const settings = json5.parse(raw);
|
|
52
|
-
// Replace secrets fields with the replacement string.
|
|
53
|
-
// Create the field if it does not exist in settings.
|
|
54
|
-
this._doNotSave.forEach(field => {
|
|
55
|
-
if (settings['AIprovider'] !== undefined) {
|
|
56
|
-
settings['AIprovider'][field] = SECRETS_REPLACEMENT;
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
await this._connector.save(id, json5.stringify(settings, null, 2));
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { PageConfig } from '@jupyterlab/coreutils';
|
|
2
|
-
import {
|
|
3
|
-
ISettingConnector,
|
|
4
|
-
ISettingRegistry
|
|
5
|
-
} from '@jupyterlab/settingregistry';
|
|
6
|
-
import { DataConnector, IDataConnector } from '@jupyterlab/statedb';
|
|
7
|
-
import { Throttler } from '@lumino/polling';
|
|
8
|
-
import * as json5 from 'json5';
|
|
9
|
-
|
|
10
|
-
import { SECRETS_REPLACEMENT } from '.';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A data connector for fetching settings.
|
|
14
|
-
*
|
|
15
|
-
* #### Notes
|
|
16
|
-
* This connector adds a query parameter to the base services setting manager.
|
|
17
|
-
*/
|
|
18
|
-
export class SettingConnector
|
|
19
|
-
extends DataConnector<ISettingRegistry.IPlugin, string>
|
|
20
|
-
implements ISettingConnector
|
|
21
|
-
{
|
|
22
|
-
constructor(connector: IDataConnector<ISettingRegistry.IPlugin, string>) {
|
|
23
|
-
super();
|
|
24
|
-
this._connector = connector;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
set doNotSave(fields: string[]) {
|
|
28
|
-
this._doNotSave = [...fields];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Fetch settings for a plugin.
|
|
33
|
-
* @param id - The plugin ID
|
|
34
|
-
*
|
|
35
|
-
* #### Notes
|
|
36
|
-
* The REST API requests are throttled at one request per plugin per 100ms.
|
|
37
|
-
*/
|
|
38
|
-
fetch(id: string): Promise<ISettingRegistry.IPlugin | undefined> {
|
|
39
|
-
const throttlers = this._throttlers;
|
|
40
|
-
if (!(id in throttlers)) {
|
|
41
|
-
throttlers[id] = new Throttler(() => this._connector.fetch(id), 100);
|
|
42
|
-
}
|
|
43
|
-
return throttlers[id].invoke();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async list(query: 'ids'): Promise<{ ids: string[] }>;
|
|
47
|
-
async list(
|
|
48
|
-
query: 'active' | 'all'
|
|
49
|
-
): Promise<{ ids: string[]; values: ISettingRegistry.IPlugin[] }>;
|
|
50
|
-
async list(
|
|
51
|
-
query: 'active' | 'all' | 'ids' = 'all'
|
|
52
|
-
): Promise<{ ids: string[]; values?: ISettingRegistry.IPlugin[] }> {
|
|
53
|
-
const { isDisabled } = PageConfig.Extension;
|
|
54
|
-
const { ids, values } = await this._connector.list(
|
|
55
|
-
query === 'ids' ? 'ids' : undefined
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
if (query === 'all') {
|
|
59
|
-
return { ids, values };
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (query === 'ids') {
|
|
63
|
-
return { ids };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
ids: ids.filter(id => !isDisabled(id)),
|
|
68
|
-
values: values.filter(({ id }) => !isDisabled(id))
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async save(id: string, raw: string): Promise<void> {
|
|
73
|
-
const settings = json5.parse(raw);
|
|
74
|
-
|
|
75
|
-
// Replace secrets fields with the replacement string.
|
|
76
|
-
// Create the field if it does not exist in settings.
|
|
77
|
-
this._doNotSave.forEach(field => {
|
|
78
|
-
if (settings['AIprovider'] !== undefined) {
|
|
79
|
-
settings['AIprovider'][field] = SECRETS_REPLACEMENT;
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
await this._connector.save(id, json5.stringify(settings, null, 2));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
private _connector: IDataConnector<ISettingRegistry.IPlugin, string>;
|
|
86
|
-
private _doNotSave: string[] = [];
|
|
87
|
-
private _throttlers: { [key: string]: Throttler } = Object.create(null);
|
|
88
|
-
}
|