@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,9 @@
|
|
|
1
|
+
import { ChatCommand, IChatCommandProvider, IInputModel } from '@jupyter/chat';
|
|
2
|
+
export declare class MentionCommandProvider implements IChatCommandProvider {
|
|
3
|
+
id: string;
|
|
4
|
+
listCommandCompletions(inputModel: IInputModel): Promise<ChatCommand[]>;
|
|
5
|
+
onSubmit(inputModel: IInputModel): Promise<void>;
|
|
6
|
+
private _command;
|
|
7
|
+
private _regex;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=mention.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Avatar } from '@jupyter/chat';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { DEFAULT_PERSONA } from '../tokens';
|
|
4
|
+
export class MentionCommandProvider {
|
|
5
|
+
id = '@jupyternaut/persona:mention';
|
|
6
|
+
async listCommandCompletions(inputModel) {
|
|
7
|
+
const match = inputModel.currentWord?.match(this._regex)?.[0];
|
|
8
|
+
if (!match) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
if (this._command.name.startsWith(match)) {
|
|
12
|
+
return [this._command];
|
|
13
|
+
}
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
async onSubmit(inputModel) {
|
|
17
|
+
const input = inputModel.value;
|
|
18
|
+
const match = input.match(this._regex)?.[0];
|
|
19
|
+
if (this._command.name === match) {
|
|
20
|
+
inputModel.addMention?.(DEFAULT_PERSONA);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
_command = {
|
|
24
|
+
name: `@${DEFAULT_PERSONA.mention_name}`,
|
|
25
|
+
providerId: this.id,
|
|
26
|
+
icon: React.createElement(Avatar, { user: DEFAULT_PERSONA }),
|
|
27
|
+
spaceOnAccept: true
|
|
28
|
+
};
|
|
29
|
+
_regex = /@([\w-]*)/g;
|
|
30
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { IProviderRegistry } from '@jupyternaut/agent';
|
|
2
|
+
import type { IAISettingsModel } from '@jupyternaut/agent';
|
|
3
|
+
import { CompletionHandler, IInlineCompletionContext, IInlineCompletionList, IInlineCompletionProvider } from '@jupyterlab/completer';
|
|
4
|
+
import { ISecretsManager } from 'jupyter-secrets-manager';
|
|
5
|
+
/**
|
|
6
|
+
* Configuration interface for provider-specific completion behavior
|
|
7
|
+
*/
|
|
8
|
+
export interface IProviderCompletionConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Temperature setting for the provider
|
|
11
|
+
*/
|
|
12
|
+
temperature?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Whether the provider supports fill-in-the-middle completion
|
|
15
|
+
*/
|
|
16
|
+
supportsFillInMiddle?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether to set filterText for this provider
|
|
19
|
+
*/
|
|
20
|
+
useFilterText?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The generic completion provider to register to the completion provider manager.
|
|
24
|
+
*/
|
|
25
|
+
export declare class AICompletionProvider implements IInlineCompletionProvider {
|
|
26
|
+
/**
|
|
27
|
+
* Construct a new completion provider.
|
|
28
|
+
*/
|
|
29
|
+
constructor(options: AICompletionProvider.IOptions);
|
|
30
|
+
/**
|
|
31
|
+
* The unique identifier of the provider.
|
|
32
|
+
*/
|
|
33
|
+
readonly identifier = "@jupyternaut/persona:completer";
|
|
34
|
+
/**
|
|
35
|
+
* Get the current completer name based on settings.
|
|
36
|
+
*/
|
|
37
|
+
get name(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Get the system prompt for the completion.
|
|
40
|
+
*/
|
|
41
|
+
get systemPrompt(): string;
|
|
42
|
+
/**
|
|
43
|
+
* Fetch completion items based on the request and context.
|
|
44
|
+
*/
|
|
45
|
+
fetch(request: CompletionHandler.IRequest, context: IInlineCompletionContext): Promise<IInlineCompletionList>;
|
|
46
|
+
/**
|
|
47
|
+
* Update the language model based on current settings.
|
|
48
|
+
*/
|
|
49
|
+
private _updateModel;
|
|
50
|
+
/**
|
|
51
|
+
* Extract context from notebook cells
|
|
52
|
+
*/
|
|
53
|
+
private _extractNotebookContext;
|
|
54
|
+
/**
|
|
55
|
+
* Get provider-specific completion configuration
|
|
56
|
+
*/
|
|
57
|
+
private _getProviderCompletionConfig;
|
|
58
|
+
private _settingsModel;
|
|
59
|
+
private _providerRegistry?;
|
|
60
|
+
private _model;
|
|
61
|
+
private _secretsManager?;
|
|
62
|
+
}
|
|
63
|
+
export declare namespace AICompletionProvider {
|
|
64
|
+
/**
|
|
65
|
+
* The options for the constructor of the completion provider.
|
|
66
|
+
*/
|
|
67
|
+
interface IOptions {
|
|
68
|
+
/**
|
|
69
|
+
* The AI settings model.
|
|
70
|
+
*/
|
|
71
|
+
settingsModel: IAISettingsModel;
|
|
72
|
+
/**
|
|
73
|
+
* The provider registry
|
|
74
|
+
*/
|
|
75
|
+
providerRegistry?: IProviderRegistry;
|
|
76
|
+
/**
|
|
77
|
+
* The secrets manager.
|
|
78
|
+
*/
|
|
79
|
+
secretsManager?: ISecretsManager;
|
|
80
|
+
/**
|
|
81
|
+
* The token used to request the secrets manager.
|
|
82
|
+
*/
|
|
83
|
+
token: symbol | null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=completion-provider.d.ts.map
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { createCompletionModel, SECRETS_NAMESPACE } from '@jupyternaut/agent';
|
|
2
|
+
import { NotebookPanel } from '@jupyterlab/notebook';
|
|
3
|
+
import { generateText } from 'ai';
|
|
4
|
+
/**
|
|
5
|
+
* Default temperature for code completion (lower than chat for more deterministic results)
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_COMPLETION_TEMPERATURE = 0.3;
|
|
8
|
+
/**
|
|
9
|
+
* The generic completion provider to register to the completion provider manager.
|
|
10
|
+
*/
|
|
11
|
+
export class AICompletionProvider {
|
|
12
|
+
/**
|
|
13
|
+
* Construct a new completion provider.
|
|
14
|
+
*/
|
|
15
|
+
constructor(options) {
|
|
16
|
+
Private.setToken(options.token);
|
|
17
|
+
this._settingsModel = options.settingsModel;
|
|
18
|
+
this._providerRegistry = options.providerRegistry;
|
|
19
|
+
this._secretsManager = options.secretsManager;
|
|
20
|
+
this._settingsModel.stateChanged.connect(() => {
|
|
21
|
+
this._updateModel();
|
|
22
|
+
});
|
|
23
|
+
this._updateModel();
|
|
24
|
+
// Disable the secrets manager if the token is empty.
|
|
25
|
+
if (!options.token) {
|
|
26
|
+
this._secretsManager = undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The unique identifier of the provider.
|
|
31
|
+
*/
|
|
32
|
+
identifier = '@jupyternaut/persona:completer';
|
|
33
|
+
/**
|
|
34
|
+
* Get the current completer name based on settings.
|
|
35
|
+
*/
|
|
36
|
+
get name() {
|
|
37
|
+
const activeProvider = this._settingsModel.getCompleterProvider();
|
|
38
|
+
return activeProvider ? `${activeProvider.provider}-completer` : 'none';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get the system prompt for the completion.
|
|
42
|
+
*/
|
|
43
|
+
get systemPrompt() {
|
|
44
|
+
return this._settingsModel.config.completionSystemPrompt;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Fetch completion items based on the request and context.
|
|
48
|
+
*/
|
|
49
|
+
async fetch(request, context) {
|
|
50
|
+
if (!this._model) {
|
|
51
|
+
return { items: [] };
|
|
52
|
+
}
|
|
53
|
+
const { text, offset: cursorOffset } = request;
|
|
54
|
+
const prompt = text.slice(0, cursorOffset);
|
|
55
|
+
const suffix = text.slice(cursorOffset);
|
|
56
|
+
// Get current provider settings
|
|
57
|
+
const activeProvider = this._settingsModel.getCompleterProvider();
|
|
58
|
+
if (!activeProvider) {
|
|
59
|
+
return { items: [] };
|
|
60
|
+
}
|
|
61
|
+
const provider = activeProvider.provider;
|
|
62
|
+
const providerConfig = this._getProviderCompletionConfig();
|
|
63
|
+
try {
|
|
64
|
+
let completionPrompt;
|
|
65
|
+
// Check if we're in a notebook or file and handle context accordingly
|
|
66
|
+
if (context.widget instanceof NotebookPanel) {
|
|
67
|
+
// Extract notebook context with surrounding cells
|
|
68
|
+
const contextString = this._extractNotebookContext(context, request);
|
|
69
|
+
completionPrompt = contextString;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// For files, use simpler approach
|
|
73
|
+
completionPrompt = prompt.trim();
|
|
74
|
+
// Apply fill-in-middle formatting if supported and suffix exists
|
|
75
|
+
if (providerConfig.supportsFillInMiddle && suffix.trim()) {
|
|
76
|
+
completionPrompt = `<PRE>${prompt}<SUF>${suffix}<MID>`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const { text: completion } = await generateText({
|
|
80
|
+
model: this._model,
|
|
81
|
+
prompt: completionPrompt,
|
|
82
|
+
instructions: this.systemPrompt,
|
|
83
|
+
temperature: providerConfig.temperature || 0.3
|
|
84
|
+
});
|
|
85
|
+
// Clean up FIM tags and code block markers
|
|
86
|
+
const cleanCompletion = completion
|
|
87
|
+
.replace(/<PRE>/g, '')
|
|
88
|
+
.replace(/<SUF>/g, '')
|
|
89
|
+
.replace(/<MID>/g, '')
|
|
90
|
+
.replace(/```[\s\S]*?```/g, '')
|
|
91
|
+
.trim();
|
|
92
|
+
const items = [
|
|
93
|
+
{
|
|
94
|
+
insertText: cleanCompletion,
|
|
95
|
+
filterText: providerConfig.useFilterText
|
|
96
|
+
? prompt.substring(completionPrompt.length)
|
|
97
|
+
: undefined
|
|
98
|
+
}
|
|
99
|
+
];
|
|
100
|
+
return { items };
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error(`Error fetching completions from ${provider}:`, error);
|
|
104
|
+
return { items: [] };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Update the language model based on current settings.
|
|
109
|
+
*/
|
|
110
|
+
async _updateModel() {
|
|
111
|
+
const activeProvider = this._settingsModel.getCompleterProvider();
|
|
112
|
+
if (!activeProvider) {
|
|
113
|
+
this._model = null;
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const provider = activeProvider.provider;
|
|
117
|
+
const model = activeProvider.model;
|
|
118
|
+
const baseURL = activeProvider.baseURL;
|
|
119
|
+
let apiKey;
|
|
120
|
+
if (this._secretsManager && this._settingsModel.config.useSecretsManager) {
|
|
121
|
+
const token = Private.getToken();
|
|
122
|
+
if (!token) {
|
|
123
|
+
// This should never happen, the secrets manager should be disabled.
|
|
124
|
+
console.error('@jupyternaut/persona::AICompletionProvider error: the settings manager token is not set.\nYou should disable the secrets manager from the AI settings.');
|
|
125
|
+
apiKey = '';
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
apiKey =
|
|
129
|
+
(await this._secretsManager.get(token, SECRETS_NAMESPACE, `${provider}:apiKey`))?.value ?? '';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
apiKey = this._settingsModel.getApiKey(activeProvider.id);
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
this._model = createCompletionModel({
|
|
137
|
+
provider,
|
|
138
|
+
model,
|
|
139
|
+
apiKey,
|
|
140
|
+
baseURL
|
|
141
|
+
}, this._providerRegistry);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error(`Error creating model for ${provider}:`, error);
|
|
145
|
+
this._model = null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Extract context from notebook cells
|
|
150
|
+
*/
|
|
151
|
+
_extractNotebookContext(context, request) {
|
|
152
|
+
const { text, offset: cursorOffset } = request;
|
|
153
|
+
let codeBeforeCursor = text.slice(0, cursorOffset);
|
|
154
|
+
let codeAfterCursor = text.slice(cursorOffset);
|
|
155
|
+
const notebookPanel = context.widget;
|
|
156
|
+
const notebook = notebookPanel.content;
|
|
157
|
+
const currentCellIndex = notebook.activeCellIndex;
|
|
158
|
+
const cells = notebook.widgets;
|
|
159
|
+
// For notebooks, include context from surrounding cells
|
|
160
|
+
const cellsAbove = [];
|
|
161
|
+
const cellsBelow = [];
|
|
162
|
+
// Get content from cells above current cell
|
|
163
|
+
for (let i = 0; i < currentCellIndex; i++) {
|
|
164
|
+
const cell = cells[i];
|
|
165
|
+
if (cell.model.type === 'code') {
|
|
166
|
+
const source = cell.model.sharedModel.source;
|
|
167
|
+
if (source.trim()) {
|
|
168
|
+
cellsAbove.push(source.trim());
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Get content from cells below current cell
|
|
173
|
+
for (let i = currentCellIndex + 1; i < cells.length; i++) {
|
|
174
|
+
const cell = cells[i];
|
|
175
|
+
if (cell.model.type === 'code') {
|
|
176
|
+
const source = cell.model.sharedModel.source;
|
|
177
|
+
if (source.trim()) {
|
|
178
|
+
cellsBelow.push(source.trim());
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Include cells above in the code before cursor
|
|
183
|
+
if (cellsAbove.length > 0) {
|
|
184
|
+
const cellsAboveText = cellsAbove
|
|
185
|
+
.map((cell, index) => `# Cell ${index + 1}:\n${cell}`)
|
|
186
|
+
.join('\n\n');
|
|
187
|
+
codeBeforeCursor = `${cellsAboveText}\n\n# Current cell:\n${codeBeforeCursor}`;
|
|
188
|
+
}
|
|
189
|
+
// Include cells below in the code after cursor
|
|
190
|
+
if (cellsBelow.length > 0) {
|
|
191
|
+
const cellsBelowText = cellsBelow
|
|
192
|
+
.map((cell, index) => `# Cell ${index + 1}:\n${cell}`)
|
|
193
|
+
.join('\n\n');
|
|
194
|
+
codeAfterCursor = `${codeAfterCursor}\n\n# Cells below:\n${cellsBelowText}`;
|
|
195
|
+
}
|
|
196
|
+
const parts = [];
|
|
197
|
+
// Add code before cursor
|
|
198
|
+
if (codeBeforeCursor) {
|
|
199
|
+
parts.push('# Code before cursor:');
|
|
200
|
+
parts.push(codeBeforeCursor);
|
|
201
|
+
}
|
|
202
|
+
// Add completion instruction
|
|
203
|
+
parts.push('# Complete the code at cursor position');
|
|
204
|
+
// Add code after cursor
|
|
205
|
+
if (codeAfterCursor) {
|
|
206
|
+
parts.push('# Code after cursor:');
|
|
207
|
+
parts.push(codeAfterCursor);
|
|
208
|
+
}
|
|
209
|
+
return parts.length > 1 ? parts.join('\n\n') + '\n\n' : '';
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Get provider-specific completion configuration
|
|
213
|
+
*/
|
|
214
|
+
_getProviderCompletionConfig() {
|
|
215
|
+
// Get provider-specific completion parameters
|
|
216
|
+
const activeProvider = this._settingsModel.getCompleterProvider();
|
|
217
|
+
// Use provider-specific temperature or fall back to default
|
|
218
|
+
const temperature = activeProvider?.parameters?.temperature ?? DEFAULT_COMPLETION_TEMPERATURE;
|
|
219
|
+
const supportsFillInMiddle = activeProvider?.parameters?.supportsFillInMiddle ?? false;
|
|
220
|
+
const useFilterText = activeProvider?.parameters?.useFilterText ?? false;
|
|
221
|
+
return {
|
|
222
|
+
temperature,
|
|
223
|
+
supportsFillInMiddle,
|
|
224
|
+
useFilterText
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
_settingsModel;
|
|
228
|
+
_providerRegistry;
|
|
229
|
+
_model = null;
|
|
230
|
+
_secretsManager;
|
|
231
|
+
}
|
|
232
|
+
var Private;
|
|
233
|
+
(function (Private) {
|
|
234
|
+
/**
|
|
235
|
+
* The token to use with the secrets manager, setter and getter.
|
|
236
|
+
*/
|
|
237
|
+
let secretsToken;
|
|
238
|
+
function setToken(value) {
|
|
239
|
+
secretsToken = value;
|
|
240
|
+
}
|
|
241
|
+
Private.setToken = setToken;
|
|
242
|
+
function getToken() {
|
|
243
|
+
return secretsToken;
|
|
244
|
+
}
|
|
245
|
+
Private.getToken = getToken;
|
|
246
|
+
})(Private || (Private = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './completion-provider';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
2
|
+
import type { TranslationBundle } from '@jupyterlab/translation';
|
|
3
|
+
import type { IAISettingsModel } from '@jupyternaut/agent';
|
|
4
|
+
/**
|
|
5
|
+
* The completion status props.
|
|
6
|
+
*/
|
|
7
|
+
interface ICompletionStatusProps {
|
|
8
|
+
/**
|
|
9
|
+
* The settings model.
|
|
10
|
+
*/
|
|
11
|
+
settingsModel: IAISettingsModel;
|
|
12
|
+
/**
|
|
13
|
+
* The application language translator.
|
|
14
|
+
*/
|
|
15
|
+
translator: TranslationBundle;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The completion status widget that will be added to the status bar.
|
|
19
|
+
*/
|
|
20
|
+
export declare class CompletionStatusWidget extends ReactWidget {
|
|
21
|
+
constructor(options: ICompletionStatusProps);
|
|
22
|
+
render(): JSX.Element;
|
|
23
|
+
private _props;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=completion-status.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
2
|
+
import { jupyternautIcon } from '@jupyternaut/agent';
|
|
3
|
+
import React, { useEffect, useState } from 'react';
|
|
4
|
+
const COMPLETION_STATUS_CLASS = 'jp-ai-completion-status';
|
|
5
|
+
const COMPLETION_DISABLED_CLASS = 'jp-ai-completion-disabled';
|
|
6
|
+
/**
|
|
7
|
+
* The completion status component.
|
|
8
|
+
*/
|
|
9
|
+
function CompletionStatus(props) {
|
|
10
|
+
const { translator: trans } = props;
|
|
11
|
+
const [disabled, setDisabled] = useState(true);
|
|
12
|
+
const [title, setTitle] = useState('');
|
|
13
|
+
/**
|
|
14
|
+
* Handle changes in the settings.
|
|
15
|
+
*/
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const stateChanged = (model) => {
|
|
18
|
+
if (model.config.useSameProviderForChatAndCompleter) {
|
|
19
|
+
setDisabled(false);
|
|
20
|
+
setTitle(trans.__('Completion using %1', model.getDefaultProvider()?.model ?? ''));
|
|
21
|
+
}
|
|
22
|
+
else if (model.config.activeCompleterProvider) {
|
|
23
|
+
setDisabled(false);
|
|
24
|
+
setTitle(trans.__('Completion using %1', model.getProvider(model.config.activeCompleterProvider)?.model ?? ''));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
setDisabled(true);
|
|
28
|
+
setTitle(trans.__('No completion'));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
props.settingsModel.stateChanged.connect(stateChanged);
|
|
32
|
+
stateChanged(props.settingsModel);
|
|
33
|
+
return () => {
|
|
34
|
+
props.settingsModel.stateChanged.disconnect(stateChanged);
|
|
35
|
+
};
|
|
36
|
+
}, [props.settingsModel, trans]);
|
|
37
|
+
return (React.createElement(jupyternautIcon.react, { className: disabled ? COMPLETION_DISABLED_CLASS : '', top: '2px', width: '16px', stylesheet: 'statusBar', title: title }));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The completion status widget that will be added to the status bar.
|
|
41
|
+
*/
|
|
42
|
+
export class CompletionStatusWidget extends ReactWidget {
|
|
43
|
+
constructor(options) {
|
|
44
|
+
super();
|
|
45
|
+
this.addClass(COMPLETION_STATUS_CLASS);
|
|
46
|
+
this._props = options;
|
|
47
|
+
}
|
|
48
|
+
render() {
|
|
49
|
+
return React.createElement(CompletionStatus, { ...this._props });
|
|
50
|
+
}
|
|
51
|
+
_props;
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './completion-status';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IAISettingsModel, IDiffManager, IShowCellDiffParams, IShowFileDiffParams } from '@jupyternaut/agent';
|
|
2
|
+
import { CommandRegistry } from '@lumino/commands';
|
|
3
|
+
/**
|
|
4
|
+
* Implementation of the diff manager
|
|
5
|
+
*/
|
|
6
|
+
export declare class DiffManager implements IDiffManager {
|
|
7
|
+
/**
|
|
8
|
+
* Construct a new DiffManager
|
|
9
|
+
*/
|
|
10
|
+
constructor(options: {
|
|
11
|
+
commands: CommandRegistry;
|
|
12
|
+
settingsModel: IAISettingsModel;
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Show diff between original and modified cell content
|
|
16
|
+
*/
|
|
17
|
+
showCellDiff(params: IShowCellDiffParams): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Show diff between original and modified file content
|
|
20
|
+
*/
|
|
21
|
+
showFileDiff(params: IShowFileDiffParams): Promise<void>;
|
|
22
|
+
private _commands;
|
|
23
|
+
private _settingsModel;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=diff-manager.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command IDs for unified cell diffs
|
|
3
|
+
*/
|
|
4
|
+
const UNIFIED_DIFF_COMMAND_ID = 'jupyterlab-diff:unified-cell-diff';
|
|
5
|
+
/**
|
|
6
|
+
* Command IDs for split cell diffs
|
|
7
|
+
*/
|
|
8
|
+
const SPLIT_DIFF_COMMAND_ID = 'jupyterlab-diff:split-cell-diff';
|
|
9
|
+
/**
|
|
10
|
+
* Command ID for unified file diffs
|
|
11
|
+
*/
|
|
12
|
+
const UNIFIED_FILE_DIFF_COMMAND_ID = 'jupyterlab-diff:unified-file-diff';
|
|
13
|
+
/**
|
|
14
|
+
* Implementation of the diff manager
|
|
15
|
+
*/
|
|
16
|
+
export class DiffManager {
|
|
17
|
+
/**
|
|
18
|
+
* Construct a new DiffManager
|
|
19
|
+
*/
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this._commands = options.commands;
|
|
22
|
+
this._settingsModel = options.settingsModel;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Show diff between original and modified cell content
|
|
26
|
+
*/
|
|
27
|
+
async showCellDiff(params) {
|
|
28
|
+
if (!this._settingsModel.config.showCellDiff) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const showDiffCommandId = this._settingsModel.config.diffDisplayMode === 'unified'
|
|
32
|
+
? UNIFIED_DIFF_COMMAND_ID
|
|
33
|
+
: SPLIT_DIFF_COMMAND_ID;
|
|
34
|
+
await this._commands.execute(showDiffCommandId, {
|
|
35
|
+
originalSource: params.original,
|
|
36
|
+
newSource: params.modified,
|
|
37
|
+
cellId: params.cellId,
|
|
38
|
+
showActionButtons: params.showActionButtons ?? true,
|
|
39
|
+
openDiff: params.openDiff ?? true,
|
|
40
|
+
notebookPath: params.notebookPath
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Show diff between original and modified file content
|
|
45
|
+
*/
|
|
46
|
+
async showFileDiff(params) {
|
|
47
|
+
if (!this._settingsModel.config.showFileDiff) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// File diffs only support unified view
|
|
51
|
+
await this._commands.execute(UNIFIED_FILE_DIFF_COMMAND_ID, {
|
|
52
|
+
originalSource: params.original,
|
|
53
|
+
newSource: params.modified,
|
|
54
|
+
filePath: params.filePath,
|
|
55
|
+
showActionButtons: params.showActionButtons ?? true
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
_commands;
|
|
59
|
+
_settingsModel;
|
|
60
|
+
}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IAgentManagerFactory, IAISettingsModel, IDiffManager, IProviderRegistry, IToolRegistry, ISkillRegistry } from '@jupyternaut/agent';
|
|
2
|
+
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
3
|
+
import { IPersonaRegistry } from './tokens';
|
|
4
|
+
declare const _default: (JupyterFrontEndPlugin<IProviderRegistry> | JupyterFrontEndPlugin<void> | JupyterFrontEndPlugin<IPersonaRegistry> | JupyterFrontEndPlugin<IAgentManagerFactory> | JupyterFrontEndPlugin<IAISettingsModel> | JupyterFrontEndPlugin<IDiffManager> | JupyterFrontEndPlugin<ISkillRegistry> | JupyterFrontEndPlugin<IToolRegistry>)[];
|
|
5
|
+
export default _default;
|
|
6
|
+
export * from './tokens';
|
|
7
|
+
export { processAttachments } from './process-attachments';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|