@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.
- package/lib/chat-commands/mention.d.ts +9 -0
- package/lib/chat-commands/mention.js +30 -0
- package/lib/completion/completion-provider.d.ts +86 -0
- package/lib/completion/completion-provider.js +246 -0
- package/lib/completion/index.d.ts +2 -0
- package/lib/completion/index.js +1 -0
- package/lib/components/completion-status.d.ts +26 -0
- package/lib/components/completion-status.js +52 -0
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +1 -0
- package/lib/diff-manager.d.ts +25 -0
- package/lib/diff-manager.js +60 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +522 -0
- package/lib/models/settings-model.d.ts +36 -0
- package/lib/models/settings-model.js +356 -0
- package/lib/persona-registry.d.ts +15 -0
- package/lib/persona-registry.js +29 -0
- package/lib/persona.d.ts +66 -0
- package/lib/persona.js +414 -0
- package/lib/process-attachments.d.ts +5 -0
- package/lib/process-attachments.js +287 -0
- package/lib/tokens.d.ts +101 -0
- package/lib/tokens.js +20 -0
- package/lib/widgets/ai-settings.d.ts +54 -0
- package/lib/widgets/ai-settings.js +572 -0
- package/lib/widgets/provider-config-dialog.d.ts +16 -0
- package/lib/widgets/provider-config-dialog.js +384 -0
- package/package.json +111 -7
- package/schema/settings-model.json +287 -0
- package/src/chat-commands/mention.tsx +46 -0
- package/src/completion/completion-provider.ts +350 -0
- package/src/completion/index.ts +1 -0
- package/src/components/completion-status.tsx +93 -0
- package/src/components/index.ts +1 -0
- package/src/diff-manager.ts +81 -0
- package/src/index.ts +710 -0
- package/src/models/settings-model.ts +415 -0
- package/src/persona-registry.ts +46 -0
- package/src/persona.ts +610 -0
- package/src/process-attachments.ts +369 -0
- package/src/tokens.ts +121 -0
- package/src/widgets/ai-settings.tsx +1308 -0
- package/src/widgets/provider-config-dialog.tsx +997 -0
- package/style/base.css +14 -0
- package/style/index.css +1 -0
- package/style/index.js +1 -0
- package/README.md +0 -3
- package/index.js +0 -1
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { PathExt } from '@jupyterlab/coreutils';
|
|
2
|
+
export async function processAttachments(attachments, documentManager, body, supportsImages, supportsPdf, supportsAudio) {
|
|
3
|
+
const textContents = [];
|
|
4
|
+
const includedParts = [];
|
|
5
|
+
const omittedNames = [];
|
|
6
|
+
if (!documentManager) {
|
|
7
|
+
return body;
|
|
8
|
+
}
|
|
9
|
+
for (const attachment of attachments) {
|
|
10
|
+
try {
|
|
11
|
+
if (attachment.type === 'notebook' && attachment.cells?.length) {
|
|
12
|
+
const cellContents = await readNotebookCells(attachment, documentManager);
|
|
13
|
+
if (cellContents) {
|
|
14
|
+
textContents.push(cellContents);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
let mimetype = attachment.mimetype;
|
|
19
|
+
const fileExtension = PathExt.extname(attachment.value).toLowerCase();
|
|
20
|
+
if (!mimetype) {
|
|
21
|
+
try {
|
|
22
|
+
const diskModel = await documentManager.services.contents.get(attachment.value, { content: false });
|
|
23
|
+
mimetype = diskModel?.mimetype;
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
console.warn(`Failed to fetch metadata for ${attachment.value}:`, e);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (mimetype?.startsWith('image/')) {
|
|
30
|
+
if (supportsImages) {
|
|
31
|
+
const data = await readBinaryAttachment(attachment, documentManager);
|
|
32
|
+
if (data) {
|
|
33
|
+
includedParts.push({
|
|
34
|
+
type: 'file',
|
|
35
|
+
data,
|
|
36
|
+
mediaType: mimetype
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
omittedNames.push(PathExt.basename(attachment.value));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (mimetype === 'application/pdf') {
|
|
45
|
+
if (supportsPdf) {
|
|
46
|
+
const data = await readBinaryAttachment(attachment, documentManager);
|
|
47
|
+
if (data) {
|
|
48
|
+
includedParts.push({
|
|
49
|
+
type: 'file',
|
|
50
|
+
data,
|
|
51
|
+
mediaType: mimetype,
|
|
52
|
+
filename: PathExt.basename(attachment.value)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
omittedNames.push(PathExt.basename(attachment.value));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (mimetype?.startsWith('audio/')) {
|
|
61
|
+
if (supportsAudio) {
|
|
62
|
+
const data = await readBinaryAttachment(attachment, documentManager);
|
|
63
|
+
if (data) {
|
|
64
|
+
includedParts.push({
|
|
65
|
+
type: 'file',
|
|
66
|
+
data,
|
|
67
|
+
mediaType: mimetype,
|
|
68
|
+
filename: PathExt.basename(attachment.value)
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
omittedNames.push(PathExt.basename(attachment.value));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const fileContent = await readFileAttachment(attachment, documentManager);
|
|
78
|
+
if (fileContent) {
|
|
79
|
+
const language = fileExtension === '.ipynb' ||
|
|
80
|
+
mimetype === 'application/x-ipynb+json'
|
|
81
|
+
? 'json'
|
|
82
|
+
: '';
|
|
83
|
+
textContents.push(`**File: ${attachment.value}**\n\`\`\`${language}\n${fileContent}\n\`\`\``);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.warn(`Failed to read attachment ${attachment.value}:`, error);
|
|
90
|
+
textContents.push(`**File: ${attachment.value}** (Could not read file)`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
let textPart = body;
|
|
94
|
+
if (textContents.length > 0) {
|
|
95
|
+
textPart += '\n\n--- Attached Files ---\n' + textContents.join('\n\n');
|
|
96
|
+
}
|
|
97
|
+
if (omittedNames.length > 0) {
|
|
98
|
+
textPart += `\n[Attachments omitted (not supported by this model): ${omittedNames.join(', ')}.]`;
|
|
99
|
+
}
|
|
100
|
+
return includedParts.length > 0
|
|
101
|
+
? [{ type: 'text', text: textPart }, ...includedParts]
|
|
102
|
+
: textPart;
|
|
103
|
+
}
|
|
104
|
+
async function readBinaryAttachment(attachment, documentManager) {
|
|
105
|
+
try {
|
|
106
|
+
const diskModel = await documentManager.services.contents.get(attachment.value, { content: true });
|
|
107
|
+
if (diskModel?.content && diskModel.format === 'base64') {
|
|
108
|
+
return diskModel.content.replace(/\s/g, '');
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.warn(`Failed to read binary attachment ${attachment.value}:`, error);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function readNotebookCells(attachment, documentManager) {
|
|
118
|
+
if (attachment.type !== 'notebook' || !attachment.cells) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const widget = documentManager.findWidget(attachment.value);
|
|
123
|
+
let cellData;
|
|
124
|
+
let kernelLang = 'text';
|
|
125
|
+
const ymodel = widget?.context.model.sharedModel;
|
|
126
|
+
if (ymodel) {
|
|
127
|
+
const nb = ymodel.toJSON();
|
|
128
|
+
cellData = nb.cells;
|
|
129
|
+
const lang = nb.metadata.language_info?.name ||
|
|
130
|
+
nb.metadata.kernelspec?.language ||
|
|
131
|
+
'text';
|
|
132
|
+
kernelLang = String(lang);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const model = await documentManager.services.contents.get(attachment.value, { content: true });
|
|
136
|
+
if (!model || model.type !== 'notebook') {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
cellData = model.content.cells ?? [];
|
|
140
|
+
kernelLang =
|
|
141
|
+
model.content.metadata.language_info?.name ||
|
|
142
|
+
model.content.metadata.kernelspec?.language ||
|
|
143
|
+
'text';
|
|
144
|
+
}
|
|
145
|
+
const selectedCells = attachment.cells
|
|
146
|
+
.map(cellInfo => {
|
|
147
|
+
const cell = cellData.find(c => c.id === cellInfo.id);
|
|
148
|
+
if (!cell) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const code = cell.source || '';
|
|
152
|
+
const cellType = cell.cell_type;
|
|
153
|
+
const lang = cellType === 'code' ? kernelLang : cellType;
|
|
154
|
+
let outputs = '';
|
|
155
|
+
if (cellType === 'code' && Array.isArray(cell.outputs)) {
|
|
156
|
+
const outputsArray = cell.outputs;
|
|
157
|
+
outputs = outputsArray
|
|
158
|
+
.map(output => {
|
|
159
|
+
if (output.output_type === 'stream') {
|
|
160
|
+
return output.text;
|
|
161
|
+
}
|
|
162
|
+
else if (output.output_type === 'error') {
|
|
163
|
+
const err = output;
|
|
164
|
+
return `${err.ename}: ${err.evalue}\n${(err.traceback || []).join('\n')}`;
|
|
165
|
+
}
|
|
166
|
+
else if (output.output_type === 'execute_result' ||
|
|
167
|
+
output.output_type === 'display_data') {
|
|
168
|
+
const data = output.data;
|
|
169
|
+
if (!data) {
|
|
170
|
+
return '';
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
return extractDisplay(data);
|
|
174
|
+
}
|
|
175
|
+
catch (e) {
|
|
176
|
+
console.error('Cannot extract cell output', e);
|
|
177
|
+
return '';
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return '';
|
|
181
|
+
})
|
|
182
|
+
.filter(Boolean)
|
|
183
|
+
.join('\n---\n');
|
|
184
|
+
if (outputs.length > 2000) {
|
|
185
|
+
outputs = outputs.slice(0, 2000) + '\n...[truncated]';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return (`**Cell [${cellInfo.id}] (${cellType}):**\n` +
|
|
189
|
+
`\`\`\`${lang}\n${code}\n\`\`\`` +
|
|
190
|
+
(outputs ? `\n**Outputs:**\n\`\`\`text\n${outputs}\n\`\`\`` : ''));
|
|
191
|
+
})
|
|
192
|
+
.filter(Boolean)
|
|
193
|
+
.join('\n\n');
|
|
194
|
+
return `**Notebook: ${attachment.value}**\n${selectedCells}`;
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
console.warn(`Failed to read notebook cells from ${attachment.value}:`, error);
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async function readFileAttachment(attachment, documentManager) {
|
|
202
|
+
if (attachment.type !== 'file' && attachment.type !== 'notebook') {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
const widget = documentManager.findWidget(attachment.value);
|
|
207
|
+
if (widget?.context?.model) {
|
|
208
|
+
const ymodel = widget.context.model.sharedModel;
|
|
209
|
+
if (typeof ymodel.getSource === 'function') {
|
|
210
|
+
const source = ymodel.getSource();
|
|
211
|
+
return typeof source === 'string'
|
|
212
|
+
? source
|
|
213
|
+
: JSON.stringify(source, null, 2);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const diskModel = await documentManager.services.contents.get(attachment.value, { content: true });
|
|
217
|
+
if (!diskModel?.content) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
if (diskModel.type === 'file') {
|
|
221
|
+
return diskModel.content;
|
|
222
|
+
}
|
|
223
|
+
if (diskModel.type === 'notebook') {
|
|
224
|
+
const cleaned = {
|
|
225
|
+
...diskModel,
|
|
226
|
+
cells: diskModel.content.cells.map((cell) => ({
|
|
227
|
+
...cell,
|
|
228
|
+
outputs: [],
|
|
229
|
+
execution_count: null
|
|
230
|
+
}))
|
|
231
|
+
};
|
|
232
|
+
return JSON.stringify(cleaned);
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
console.warn(`Failed to read file ${attachment.value}:`, error);
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function extractDisplay(data) {
|
|
242
|
+
const DISPLAY_PRIORITY = [
|
|
243
|
+
'application/vnd.jupyter.widget-view+json',
|
|
244
|
+
'application/javascript',
|
|
245
|
+
'text/html',
|
|
246
|
+
'image/svg+xml',
|
|
247
|
+
'image/png',
|
|
248
|
+
'image/jpeg',
|
|
249
|
+
'text/markdown',
|
|
250
|
+
'text/latex',
|
|
251
|
+
'text/plain'
|
|
252
|
+
];
|
|
253
|
+
for (const mime of DISPLAY_PRIORITY) {
|
|
254
|
+
if (!(mime in data)) {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
const value = data[mime];
|
|
258
|
+
if (!value) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
switch (mime) {
|
|
262
|
+
case 'application/vnd.jupyter.widget-view+json':
|
|
263
|
+
return `Widget: ${value.model_id ?? 'unknown model'}`;
|
|
264
|
+
case 'image/png':
|
|
265
|
+
return `.slice(0, 100)}...)`;
|
|
266
|
+
case 'image/jpeg':
|
|
267
|
+
return `.slice(0, 100)}...)`;
|
|
268
|
+
case 'image/svg+xml':
|
|
269
|
+
return String(value).slice(0, 500) + '...\n[svg truncated]';
|
|
270
|
+
case 'text/html':
|
|
271
|
+
return (String(value).slice(0, 1000) +
|
|
272
|
+
(String(value).length > 1000 ? '\n...[truncated]' : ''));
|
|
273
|
+
case 'text/markdown':
|
|
274
|
+
case 'text/latex':
|
|
275
|
+
case 'text/plain': {
|
|
276
|
+
let text = Array.isArray(value) ? value.join('') : String(value);
|
|
277
|
+
if (text.length > 2000) {
|
|
278
|
+
text = text.slice(0, 2000) + '\n...[truncated]';
|
|
279
|
+
}
|
|
280
|
+
return text;
|
|
281
|
+
}
|
|
282
|
+
default:
|
|
283
|
+
return JSON.stringify(value).slice(0, 2000);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return JSON.stringify(data).slice(0, 2000);
|
|
287
|
+
}
|
package/lib/tokens.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { IChatModel, IUser } from '@jupyter/chat';
|
|
2
|
+
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
3
|
+
import type { IAgentManager, IAISettingsModel, IProviderRegistry } from '@jupyternaut/agent';
|
|
4
|
+
import { Token } from '@lumino/coreutils';
|
|
5
|
+
import { ISignal } from '@lumino/signaling';
|
|
6
|
+
export declare const DEFAULT_PERSONA: IUser;
|
|
7
|
+
/**
|
|
8
|
+
* Command IDs namespace
|
|
9
|
+
*/
|
|
10
|
+
export declare namespace CommandIds {
|
|
11
|
+
const openSettings = "@jupyternaut/persona:open-settings";
|
|
12
|
+
const refreshSkills = "@jupyternaut/persona:refresh-skills";
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Public interface for a persona handler attached to a chat session.
|
|
16
|
+
*
|
|
17
|
+
* A persona handler links an `IAgentManager` to an `IChatModel`, listening for
|
|
18
|
+
* persona mentions and generating AI responses. Third-party extensions can
|
|
19
|
+
* consume `IPersonaHandlerRegistry` to obtain `IPersonaHandler` instances and
|
|
20
|
+
* interact with the agent (e.g. to read the active provider or update tools).
|
|
21
|
+
*/
|
|
22
|
+
export interface IPersona {
|
|
23
|
+
/**
|
|
24
|
+
* The agent manager used by this handler to generate AI responses.
|
|
25
|
+
*/
|
|
26
|
+
readonly agentManager: IAgentManager;
|
|
27
|
+
/**
|
|
28
|
+
* The chat model this handler is attached to.
|
|
29
|
+
*/
|
|
30
|
+
readonly model: IChatModel;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the persona is currently generating a response.
|
|
33
|
+
*/
|
|
34
|
+
readonly isBusy: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* A signal emitted when the busy state changes.
|
|
37
|
+
*/
|
|
38
|
+
readonly busyChanged: ISignal<IPersona, boolean>;
|
|
39
|
+
/**
|
|
40
|
+
* Whether a mention is required to trigger a response.
|
|
41
|
+
* When false, the persona responds to all non-bot messages.
|
|
42
|
+
* Defaults to true.
|
|
43
|
+
*/
|
|
44
|
+
requireMention: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Dispose of the handler and release its resources.
|
|
47
|
+
*/
|
|
48
|
+
dispose(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Rebuilds the agent history from the current chat messages.
|
|
51
|
+
* Called after restoring a saved chat.
|
|
52
|
+
*/
|
|
53
|
+
rebuildHistory(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Registry mapping chat models to their persona.
|
|
57
|
+
*
|
|
58
|
+
* Provided by `@jupyternaut/persona`. Other extensions (e.g. `@jupyterlite/ai`)
|
|
59
|
+
* can consume this token to access the agent manager associated with a given chat.
|
|
60
|
+
*/
|
|
61
|
+
export interface IPersonaRegistry {
|
|
62
|
+
/**
|
|
63
|
+
* Returns the persona registered for a given chat model, if any.
|
|
64
|
+
*/
|
|
65
|
+
get(model: IChatModel): IPersona | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Registers a persona for a given chat model.
|
|
68
|
+
*/
|
|
69
|
+
register(model: IChatModel, agentManager: IAgentManager): void;
|
|
70
|
+
/**
|
|
71
|
+
* Removes the persona registered for a given chat model.
|
|
72
|
+
*/
|
|
73
|
+
unregister(model: IChatModel): void;
|
|
74
|
+
/**
|
|
75
|
+
* A signal emitting whenever a new persona is registered.
|
|
76
|
+
*/
|
|
77
|
+
readonly personaAdded: ISignal<IPersonaRegistry, IPersona>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The options to build a persona registry.
|
|
81
|
+
*/
|
|
82
|
+
export interface IPersonaRegistryOptions {
|
|
83
|
+
/**
|
|
84
|
+
* The persona used by the registry.
|
|
85
|
+
*/
|
|
86
|
+
persona: IUser;
|
|
87
|
+
/**
|
|
88
|
+
* The agent settings model, used to process attachments in persona.
|
|
89
|
+
*/
|
|
90
|
+
settingsModel: IAISettingsModel;
|
|
91
|
+
/**
|
|
92
|
+
* The optional provider registry, used to process attachments in persona.
|
|
93
|
+
*/
|
|
94
|
+
providerRegistry?: IProviderRegistry;
|
|
95
|
+
/**
|
|
96
|
+
* The optional document manager, used to process attachments in persona.
|
|
97
|
+
*/
|
|
98
|
+
documentManager?: IDocumentManager;
|
|
99
|
+
}
|
|
100
|
+
export declare const IPersonaRegistry: Token<IPersonaRegistry>;
|
|
101
|
+
//# sourceMappingURL=tokens.d.ts.map
|
package/lib/tokens.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AI_AVATAR } from '@jupyternaut/agent';
|
|
2
|
+
import { Token } from '@lumino/coreutils';
|
|
3
|
+
export const DEFAULT_PERSONA = {
|
|
4
|
+
username: 'jupyternaut-frontend',
|
|
5
|
+
display_name: 'Jupyternaut',
|
|
6
|
+
initials: 'JF',
|
|
7
|
+
color: '#2196F3',
|
|
8
|
+
avatar_url: AI_AVATAR,
|
|
9
|
+
bot: true,
|
|
10
|
+
mention_name: 'jupyternaut-frontend'
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Command IDs namespace
|
|
14
|
+
*/
|
|
15
|
+
export var CommandIds;
|
|
16
|
+
(function (CommandIds) {
|
|
17
|
+
CommandIds.openSettings = '@jupyternaut/persona:open-settings';
|
|
18
|
+
CommandIds.refreshSkills = '@jupyternaut/persona:refresh-skills';
|
|
19
|
+
})(CommandIds || (CommandIds = {}));
|
|
20
|
+
export const IPersonaRegistry = new Token('@jupyternaut/persona:IPersonaHandlerRegistry');
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { IAgentManagerFactory, IAISecretsAccess, IAISettingsModel, IProviderRegistry } from '@jupyternaut/agent';
|
|
2
|
+
import { IThemeManager } from '@jupyterlab/apputils';
|
|
3
|
+
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
4
|
+
import type { TranslationBundle } from '@jupyterlab/translation';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* A JupyterLab widget for AI settings configuration
|
|
8
|
+
*/
|
|
9
|
+
export declare class AISettingsWidget extends ReactWidget {
|
|
10
|
+
/**
|
|
11
|
+
* Construct a new AI settings widget
|
|
12
|
+
* @param options - The options for initializing the widget
|
|
13
|
+
*/
|
|
14
|
+
constructor(options: AISettingsWidget.IOptions);
|
|
15
|
+
/**
|
|
16
|
+
* Render the AI settings component
|
|
17
|
+
* @returns A React element containing the AI settings interface
|
|
18
|
+
*/
|
|
19
|
+
protected render(): React.ReactElement;
|
|
20
|
+
private _settingsModel;
|
|
21
|
+
private _agentManagerFactory?;
|
|
22
|
+
private _themeManager?;
|
|
23
|
+
private _providerRegistry;
|
|
24
|
+
private _secretsAccess?;
|
|
25
|
+
private _trans;
|
|
26
|
+
private _mcpServerRenderer?;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Namespace for AISettingsWidget types and interfaces
|
|
30
|
+
*/
|
|
31
|
+
export declare namespace AISettingsWidget {
|
|
32
|
+
/**
|
|
33
|
+
* Options interface for constructing an AISettingsWidget
|
|
34
|
+
*/
|
|
35
|
+
interface IOptions {
|
|
36
|
+
settingsModel: IAISettingsModel;
|
|
37
|
+
agentManagerFactory?: IAgentManagerFactory;
|
|
38
|
+
themeManager?: IThemeManager;
|
|
39
|
+
providerRegistry: IProviderRegistry;
|
|
40
|
+
/**
|
|
41
|
+
* Access to provider secrets in the shared namespace.
|
|
42
|
+
*/
|
|
43
|
+
secretsAccess: IAISecretsAccess;
|
|
44
|
+
/**
|
|
45
|
+
* The application language translation bundle.
|
|
46
|
+
*/
|
|
47
|
+
trans: TranslationBundle;
|
|
48
|
+
/**
|
|
49
|
+
* The renderer for the MCP settings.
|
|
50
|
+
*/
|
|
51
|
+
mcpServerRenderer?: React.ComponentType<any>;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=ai-settings.d.ts.map
|