@jupyterlite/ai 0.11.1 → 0.12.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/agent.d.ts +37 -5
- package/lib/agent.js +142 -96
- package/lib/chat-commands/clear.d.ts +8 -0
- package/lib/chat-commands/clear.js +30 -0
- package/lib/chat-commands/index.d.ts +2 -0
- package/lib/chat-commands/index.js +2 -0
- package/lib/chat-commands/skills.d.ts +19 -0
- package/lib/chat-commands/skills.js +57 -0
- package/lib/chat-model.d.ts +8 -0
- package/lib/chat-model.js +35 -3
- package/lib/index.d.ts +3 -3
- package/lib/index.js +187 -10
- package/lib/models/settings-model.d.ts +1 -0
- package/lib/models/settings-model.js +61 -14
- package/lib/providers/built-in-providers.js +5 -7
- package/lib/skills/index.d.ts +4 -0
- package/lib/skills/index.js +7 -0
- package/lib/skills/parse-skill.d.ts +25 -0
- package/lib/skills/parse-skill.js +69 -0
- package/lib/skills/skill-loader.d.ts +25 -0
- package/lib/skills/skill-loader.js +133 -0
- package/lib/skills/skill-registry.d.ts +31 -0
- package/lib/skills/skill-registry.js +100 -0
- package/lib/skills/types.d.ts +29 -0
- package/lib/skills/types.js +5 -0
- package/lib/tokens.d.ts +33 -0
- package/lib/tokens.js +5 -0
- package/lib/tools/skills.d.ts +9 -0
- package/lib/tools/skills.js +73 -0
- package/lib/widgets/ai-settings.js +33 -1
- package/package.json +10 -9
- package/schema/settings-model.json +8 -1
- package/src/agent.ts +198 -102
- package/src/chat-commands/clear.ts +46 -0
- package/src/chat-commands/index.ts +2 -0
- package/src/chat-commands/skills.ts +87 -0
- package/src/chat-model.ts +48 -10
- package/src/index.ts +242 -5
- package/src/models/settings-model.ts +64 -15
- package/src/providers/built-in-providers.ts +5 -7
- package/src/skills/index.ts +14 -0
- package/src/skills/parse-skill.ts +91 -0
- package/src/skills/skill-loader.ts +175 -0
- package/src/skills/skill-registry.ts +137 -0
- package/src/skills/types.ts +37 -0
- package/src/tokens.ts +56 -0
- package/src/tools/skills.ts +84 -0
- package/src/widgets/ai-settings.tsx +75 -0
package/lib/agent.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { type Tool } from 'ai';
|
|
|
3
3
|
import { ISecretsManager } from 'jupyter-secrets-manager';
|
|
4
4
|
import { AISettingsModel } from './models/settings-model';
|
|
5
5
|
import type { IProviderRegistry } from './tokens';
|
|
6
|
-
import { ITool, IToolRegistry, ITokenUsage } from './tokens';
|
|
6
|
+
import { ISkillRegistry, ITool, IToolRegistry, ITokenUsage } from './tokens';
|
|
7
7
|
type ToolMap = Record<string, Tool>;
|
|
8
8
|
export declare namespace AgentManagerFactory {
|
|
9
9
|
interface IOptions {
|
|
@@ -11,6 +11,10 @@ export declare namespace AgentManagerFactory {
|
|
|
11
11
|
* The settings model.
|
|
12
12
|
*/
|
|
13
13
|
settingsModel: AISettingsModel;
|
|
14
|
+
/**
|
|
15
|
+
* The skill registry for discovering skills.
|
|
16
|
+
*/
|
|
17
|
+
skillRegistry?: ISkillRegistry;
|
|
14
18
|
/**
|
|
15
19
|
* The secrets manager.
|
|
16
20
|
*/
|
|
@@ -52,12 +56,17 @@ export declare class AgentManagerFactory {
|
|
|
52
56
|
* Sets up the agent with model configuration, tools, and MCP servers.
|
|
53
57
|
*/
|
|
54
58
|
private _initializeAgents;
|
|
59
|
+
/**
|
|
60
|
+
* Refresh skill snapshots across all agents.
|
|
61
|
+
*/
|
|
62
|
+
refreshSkillSnapshots(): void;
|
|
55
63
|
private _agentManagers;
|
|
56
64
|
private _settingsModel;
|
|
65
|
+
private _skillRegistry?;
|
|
57
66
|
private _secretsManager?;
|
|
58
67
|
private _mcpClients;
|
|
59
68
|
private _mcpConnectionChanged;
|
|
60
|
-
private
|
|
69
|
+
private _initQueue;
|
|
61
70
|
}
|
|
62
71
|
/**
|
|
63
72
|
* Event type mapping for type safety with inlined interface definitions
|
|
@@ -123,6 +132,10 @@ export interface IAgentManagerOptions {
|
|
|
123
132
|
* Optional provider registry for model creation
|
|
124
133
|
*/
|
|
125
134
|
providerRegistry?: IProviderRegistry;
|
|
135
|
+
/**
|
|
136
|
+
* The skill registry for discovering skills.
|
|
137
|
+
*/
|
|
138
|
+
skillRegistry?: ISkillRegistry;
|
|
126
139
|
/**
|
|
127
140
|
* The secrets manager.
|
|
128
141
|
*/
|
|
@@ -164,6 +177,10 @@ export declare class AgentManager {
|
|
|
164
177
|
* Signal emitted when token usage statistics change.
|
|
165
178
|
*/
|
|
166
179
|
get tokenUsageChanged(): ISignal<this, ITokenUsage>;
|
|
180
|
+
/**
|
|
181
|
+
* Refresh the skills snapshot and rebuild the agent if resources are ready.
|
|
182
|
+
*/
|
|
183
|
+
refreshSkills(): void;
|
|
167
184
|
/**
|
|
168
185
|
* The active provider for this agent.
|
|
169
186
|
*/
|
|
@@ -220,6 +237,18 @@ export declare class AgentManager {
|
|
|
220
237
|
* Sets up the agent with model configuration, tools, and MCP tools.
|
|
221
238
|
*/
|
|
222
239
|
initializeAgent: (mcpTools?: ToolMap) => Promise<void>;
|
|
240
|
+
/**
|
|
241
|
+
* Refresh the in-memory skills snapshot from the skill registry.
|
|
242
|
+
*/
|
|
243
|
+
private _refreshSkills;
|
|
244
|
+
/**
|
|
245
|
+
* Prepare model, tools, and settings needed to (re)build the agent.
|
|
246
|
+
*/
|
|
247
|
+
private _prepareAgentConfig;
|
|
248
|
+
/**
|
|
249
|
+
* Rebuild the agent using cached resources and the current skills snapshot.
|
|
250
|
+
*/
|
|
251
|
+
private _rebuildAgent;
|
|
223
252
|
/**
|
|
224
253
|
* Processes the stream result from agent execution.
|
|
225
254
|
* Handles message streaming, tool calls, and emits appropriate events.
|
|
@@ -262,26 +291,29 @@ export declare class AgentManager {
|
|
|
262
291
|
*/
|
|
263
292
|
private _createModel;
|
|
264
293
|
/**
|
|
265
|
-
* Enhances the base system prompt with
|
|
294
|
+
* Enhances the base system prompt with dynamic context like skills.
|
|
266
295
|
* @param baseSystemPrompt The base system prompt from settings
|
|
267
|
-
* @returns The enhanced system prompt with
|
|
296
|
+
* @returns The enhanced system prompt with dynamic additions
|
|
268
297
|
*/
|
|
269
298
|
private _getEnhancedSystemPrompt;
|
|
270
299
|
private _settingsModel;
|
|
271
300
|
private _toolRegistry?;
|
|
272
301
|
private _providerRegistry?;
|
|
302
|
+
private _skillRegistry?;
|
|
273
303
|
private _secretsManager?;
|
|
274
304
|
private _selectedToolNames;
|
|
275
305
|
private _agent;
|
|
276
306
|
private _history;
|
|
277
307
|
private _mcpTools;
|
|
278
|
-
private _isInitializing;
|
|
279
308
|
private _controller;
|
|
280
309
|
private _agentEvent;
|
|
281
310
|
private _tokenUsage;
|
|
282
311
|
private _tokenUsageChanged;
|
|
283
312
|
private _activeProvider;
|
|
284
313
|
private _activeProviderChanged;
|
|
314
|
+
private _skills;
|
|
315
|
+
private _initQueue;
|
|
316
|
+
private _agentConfig;
|
|
285
317
|
private _pendingApprovals;
|
|
286
318
|
}
|
|
287
319
|
export {};
|
package/lib/agent.js
CHANGED
|
@@ -7,9 +7,15 @@ export class AgentManagerFactory {
|
|
|
7
7
|
constructor(options) {
|
|
8
8
|
Private.setToken(options.token);
|
|
9
9
|
this._settingsModel = options.settingsModel;
|
|
10
|
+
this._skillRegistry = options.skillRegistry;
|
|
10
11
|
this._secretsManager = options.secretsManager;
|
|
11
12
|
this._mcpClients = [];
|
|
12
13
|
this._mcpConnectionChanged = new Signal(this);
|
|
14
|
+
if (this._skillRegistry) {
|
|
15
|
+
this._skillRegistry.skillsChanged.connect(() => {
|
|
16
|
+
this.refreshSkillSnapshots();
|
|
17
|
+
});
|
|
18
|
+
}
|
|
13
19
|
// Initialize agent on construction
|
|
14
20
|
this._initializeAgents().catch(error => console.warn('Failed to initialize agent in constructor:', error));
|
|
15
21
|
// Listen for settings changes
|
|
@@ -18,6 +24,7 @@ export class AgentManagerFactory {
|
|
|
18
24
|
createAgent(options) {
|
|
19
25
|
const agentManager = new AgentManager({
|
|
20
26
|
...options,
|
|
27
|
+
skillRegistry: this._skillRegistry,
|
|
21
28
|
secretsManager: this._secretsManager
|
|
22
29
|
});
|
|
23
30
|
this._agentManagers.push(agentManager);
|
|
@@ -106,30 +113,37 @@ export class AgentManagerFactory {
|
|
|
106
113
|
* Sets up the agent with model configuration, tools, and MCP servers.
|
|
107
114
|
*/
|
|
108
115
|
async _initializeAgents() {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
116
|
+
this._initQueue = this._initQueue
|
|
117
|
+
.catch(() => undefined)
|
|
118
|
+
.then(async () => {
|
|
119
|
+
try {
|
|
120
|
+
await this._initializeMCPClients();
|
|
121
|
+
const mcpTools = await this.getMCPTools();
|
|
122
|
+
this._agentManagers.forEach(manager => {
|
|
123
|
+
manager.initializeAgent(mcpTools);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
console.warn('Failed to initialize agents:', error);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return this._initQueue;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Refresh skill snapshots across all agents.
|
|
134
|
+
*/
|
|
135
|
+
refreshSkillSnapshots() {
|
|
136
|
+
this._agentManagers.forEach(manager => {
|
|
137
|
+
manager.refreshSkills();
|
|
138
|
+
});
|
|
126
139
|
}
|
|
127
140
|
_agentManagers = [];
|
|
128
141
|
_settingsModel;
|
|
142
|
+
_skillRegistry;
|
|
129
143
|
_secretsManager;
|
|
130
144
|
_mcpClients;
|
|
131
145
|
_mcpConnectionChanged;
|
|
132
|
-
|
|
146
|
+
_initQueue = Promise.resolve();
|
|
133
147
|
}
|
|
134
148
|
/**
|
|
135
149
|
* Default parameter values for agent configuration
|
|
@@ -151,12 +165,12 @@ export class AgentManager {
|
|
|
151
165
|
this._settingsModel = options.settingsModel;
|
|
152
166
|
this._toolRegistry = options.toolRegistry;
|
|
153
167
|
this._providerRegistry = options.providerRegistry;
|
|
168
|
+
this._skillRegistry = options.skillRegistry;
|
|
154
169
|
this._secretsManager = options.secretsManager;
|
|
155
170
|
this._selectedToolNames = [];
|
|
156
171
|
this._agent = null;
|
|
157
172
|
this._history = [];
|
|
158
173
|
this._mcpTools = {};
|
|
159
|
-
this._isInitializing = false;
|
|
160
174
|
this._controller = null;
|
|
161
175
|
this._agentEvent = new Signal(this);
|
|
162
176
|
this._tokenUsage = options.tokenUsage ?? {
|
|
@@ -164,6 +178,8 @@ export class AgentManager {
|
|
|
164
178
|
outputTokens: 0
|
|
165
179
|
};
|
|
166
180
|
this._tokenUsageChanged = new Signal(this);
|
|
181
|
+
this._skills = [];
|
|
182
|
+
this._agentConfig = null;
|
|
167
183
|
this.activeProvider =
|
|
168
184
|
options.activeProvider ?? this._settingsModel.config.defaultProvider;
|
|
169
185
|
// Initialize selected tools to all available tools by default
|
|
@@ -195,6 +211,20 @@ export class AgentManager {
|
|
|
195
211
|
get tokenUsageChanged() {
|
|
196
212
|
return this._tokenUsageChanged;
|
|
197
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Refresh the skills snapshot and rebuild the agent if resources are ready.
|
|
216
|
+
*/
|
|
217
|
+
refreshSkills() {
|
|
218
|
+
this._initQueue = this._initQueue
|
|
219
|
+
.catch(() => undefined)
|
|
220
|
+
.then(async () => {
|
|
221
|
+
this._refreshSkills();
|
|
222
|
+
if (!this._agentConfig) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
this._rebuildAgent();
|
|
226
|
+
});
|
|
227
|
+
}
|
|
198
228
|
/**
|
|
199
229
|
* The active provider for this agent.
|
|
200
230
|
*/
|
|
@@ -390,48 +420,83 @@ export class AgentManager {
|
|
|
390
420
|
* Sets up the agent with model configuration, tools, and MCP tools.
|
|
391
421
|
*/
|
|
392
422
|
initializeAgent = async (mcpTools) => {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
this._mcpTools = mcpTools;
|
|
423
|
+
this._initQueue = this._initQueue
|
|
424
|
+
.catch(() => undefined)
|
|
425
|
+
.then(async () => {
|
|
426
|
+
try {
|
|
427
|
+
this._refreshSkills();
|
|
428
|
+
await this._prepareAgentConfig(mcpTools);
|
|
429
|
+
this._rebuildAgent();
|
|
401
430
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
this.
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
? this._getEnhancedSystemPrompt(config.systemPrompt || '')
|
|
417
|
-
: config.systemPrompt || 'You are a helpful assistant.';
|
|
418
|
-
this._agent = new ToolLoopAgent({
|
|
419
|
-
model,
|
|
420
|
-
instructions,
|
|
421
|
-
tools,
|
|
422
|
-
temperature,
|
|
423
|
-
maxOutputTokens: maxTokens,
|
|
424
|
-
stopWhen: stepCountIs(maxTurns)
|
|
425
|
-
});
|
|
431
|
+
catch (error) {
|
|
432
|
+
console.warn('Failed to initialize agent:', error);
|
|
433
|
+
this._agent = null;
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
return this._initQueue;
|
|
437
|
+
};
|
|
438
|
+
/**
|
|
439
|
+
* Refresh the in-memory skills snapshot from the skill registry.
|
|
440
|
+
*/
|
|
441
|
+
_refreshSkills() {
|
|
442
|
+
if (!this._skillRegistry) {
|
|
443
|
+
this._skills = [];
|
|
444
|
+
return;
|
|
426
445
|
}
|
|
427
|
-
|
|
428
|
-
|
|
446
|
+
this._skills = this._skillRegistry.listSkills();
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Prepare model, tools, and settings needed to (re)build the agent.
|
|
450
|
+
*/
|
|
451
|
+
async _prepareAgentConfig(mcpTools) {
|
|
452
|
+
const config = this._settingsModel.config;
|
|
453
|
+
if (mcpTools !== undefined) {
|
|
454
|
+
this._mcpTools = mcpTools;
|
|
455
|
+
}
|
|
456
|
+
const model = await this._createModel();
|
|
457
|
+
const shouldUseTools = !!(config.toolsEnabled &&
|
|
458
|
+
this._selectedToolNames.length > 0 &&
|
|
459
|
+
this._toolRegistry &&
|
|
460
|
+
Object.keys(this._toolRegistry.tools).length > 0 &&
|
|
461
|
+
this._supportsToolCalling());
|
|
462
|
+
const tools = shouldUseTools
|
|
463
|
+
? { ...this.selectedAgentTools, ...this._mcpTools }
|
|
464
|
+
: this._mcpTools;
|
|
465
|
+
const activeProviderConfig = this._settingsModel.getProvider(this._activeProvider);
|
|
466
|
+
const temperature = activeProviderConfig?.parameters?.temperature ?? DEFAULT_TEMPERATURE;
|
|
467
|
+
const maxTokens = activeProviderConfig?.parameters?.maxOutputTokens;
|
|
468
|
+
const maxTurns = activeProviderConfig?.parameters?.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
469
|
+
this._agentConfig = {
|
|
470
|
+
model,
|
|
471
|
+
tools,
|
|
472
|
+
temperature,
|
|
473
|
+
maxOutputTokens: maxTokens,
|
|
474
|
+
maxTurns,
|
|
475
|
+
baseSystemPrompt: config.systemPrompt || '',
|
|
476
|
+
shouldUseTools
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Rebuild the agent using cached resources and the current skills snapshot.
|
|
481
|
+
*/
|
|
482
|
+
_rebuildAgent() {
|
|
483
|
+
if (!this._agentConfig) {
|
|
429
484
|
this._agent = null;
|
|
485
|
+
return;
|
|
430
486
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
487
|
+
const { model, tools, temperature, maxOutputTokens, maxTurns, baseSystemPrompt, shouldUseTools } = this._agentConfig;
|
|
488
|
+
const instructions = shouldUseTools
|
|
489
|
+
? this._getEnhancedSystemPrompt(baseSystemPrompt)
|
|
490
|
+
: baseSystemPrompt || 'You are a helpful assistant.';
|
|
491
|
+
this._agent = new ToolLoopAgent({
|
|
492
|
+
model,
|
|
493
|
+
instructions,
|
|
494
|
+
tools,
|
|
495
|
+
temperature,
|
|
496
|
+
maxOutputTokens,
|
|
497
|
+
stopWhen: stepCountIs(maxTurns)
|
|
498
|
+
});
|
|
499
|
+
}
|
|
435
500
|
/**
|
|
436
501
|
* Processes the stream result from agent execution.
|
|
437
502
|
* Handles message streaming, tool calls, and emits appropriate events.
|
|
@@ -630,67 +695,48 @@ export class AgentManager {
|
|
|
630
695
|
}, this._providerRegistry);
|
|
631
696
|
}
|
|
632
697
|
/**
|
|
633
|
-
* Enhances the base system prompt with
|
|
698
|
+
* Enhances the base system prompt with dynamic context like skills.
|
|
634
699
|
* @param baseSystemPrompt The base system prompt from settings
|
|
635
|
-
* @returns The enhanced system prompt with
|
|
700
|
+
* @returns The enhanced system prompt with dynamic additions
|
|
636
701
|
*/
|
|
637
702
|
_getEnhancedSystemPrompt(baseSystemPrompt) {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
2. THEN: Execute tools (these will show automatically with step numbers)
|
|
644
|
-
3. FINALLY: Provide a concise summary of what was accomplished
|
|
645
|
-
|
|
646
|
-
Example flow:
|
|
647
|
-
- "I'll help you create a notebook with example cells. Let me first create the file structure, then add Python and Markdown cells."
|
|
648
|
-
- [Tool executions happen with automatic step display]
|
|
649
|
-
- "Successfully created your notebook with 3 cells: a title, code example, and visualization cell."
|
|
650
|
-
|
|
651
|
-
Guidelines:
|
|
652
|
-
- Start responses with your plan/approach before tool execution
|
|
653
|
-
- Let the system handle tool execution display (don't duplicate details)
|
|
654
|
-
- End with a brief summary of accomplishments
|
|
655
|
-
- Use natural, conversational tone throughout
|
|
656
|
-
|
|
657
|
-
PRIMARY TOOL USAGE - COMMAND-BASED OPERATIONS:
|
|
658
|
-
Most operations in JupyterLab should be performed using the command system:
|
|
659
|
-
1. Use 'discover_commands' to find available commands and their metadata
|
|
660
|
-
2. Use 'execute_command' to perform the actual operation
|
|
703
|
+
if (this._skills.length === 0) {
|
|
704
|
+
return baseSystemPrompt;
|
|
705
|
+
}
|
|
706
|
+
const lines = this._skills.map(skill => `- ${skill.name}: ${skill.description}`);
|
|
707
|
+
const skillsPrompt = `
|
|
661
708
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
709
|
+
AGENT SKILLS:
|
|
710
|
+
Skills are provided via the skills registry and accessed through tools (not commands).
|
|
711
|
+
When a skill is relevant to the user's task, activate it by calling load_skill with the skill name to load its full instructions, then follow those instructions.
|
|
712
|
+
If the user explicitly asks for the latest list of skills, call discover_skills (optionally with a query).
|
|
713
|
+
Do NOT call discover_skills just to list skills; use the preloaded snapshot below instead unless you need to verify a skill not present in the snapshot.
|
|
714
|
+
If the load_skill result includes a non-empty "resources" array, those are bundled files (scripts, references, templates) you MUST load before proceeding. Only load the listed resource paths; never invent resource names. For each resource path, execute load_skill again with the resource argument, e.g.: load_skill({ name: "<skill>", resource: "<path>" }). Load all listed resources before starting the task.
|
|
666
715
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
- To specify by language: { "kernelPreference": { "language": "python" } } or { "kernelPreference": { "language": "julia" } }
|
|
670
|
-
- To specify by kernel name: { "kernelPreference": { "name": "python3" } } or { "kernelPreference": { "name": "julia-1.10" } }
|
|
671
|
-
- Example: execute_command with commandId="notebook:create-new" and args={ "kernelPreference": { "language": "python" } }
|
|
672
|
-
- Example: execute_command with commandId="console:create" and args={ "kernelPreference": { "name": "python3" } }
|
|
673
|
-
- Common kernel names: "python3" (Python), "julia-1.10" (Julia), "ir" (R), "xpython" (xeus-python)
|
|
674
|
-
- If unsure of exact kernel name, prefer using "language" which will match any kernel supporting that language
|
|
716
|
+
AVAILABLE SKILLS (preloaded snapshot):
|
|
717
|
+
${lines.join('\n')}
|
|
675
718
|
`;
|
|
676
|
-
return baseSystemPrompt +
|
|
719
|
+
return baseSystemPrompt + skillsPrompt;
|
|
677
720
|
}
|
|
678
721
|
// Private attributes
|
|
679
722
|
_settingsModel;
|
|
680
723
|
_toolRegistry;
|
|
681
724
|
_providerRegistry;
|
|
725
|
+
_skillRegistry;
|
|
682
726
|
_secretsManager;
|
|
683
727
|
_selectedToolNames;
|
|
684
728
|
_agent;
|
|
685
729
|
_history;
|
|
686
730
|
_mcpTools;
|
|
687
|
-
_isInitializing;
|
|
688
731
|
_controller;
|
|
689
732
|
_agentEvent;
|
|
690
733
|
_tokenUsage;
|
|
691
734
|
_tokenUsageChanged;
|
|
692
735
|
_activeProvider = '';
|
|
693
736
|
_activeProviderChanged = new Signal(this);
|
|
737
|
+
_skills;
|
|
738
|
+
_initQueue = Promise.resolve();
|
|
739
|
+
_agentConfig;
|
|
694
740
|
_pendingApprovals = new Map();
|
|
695
741
|
}
|
|
696
742
|
var Private;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ChatCommand, IChatCommandProvider, IInputModel } from '@jupyter/chat';
|
|
2
|
+
export declare class ClearCommandProvider implements IChatCommandProvider {
|
|
3
|
+
id: string;
|
|
4
|
+
listCommandCompletions(inputModel: IInputModel): Promise<ChatCommand[]>;
|
|
5
|
+
onSubmit(inputModel: IInputModel): Promise<void>;
|
|
6
|
+
private _command;
|
|
7
|
+
private _regex;
|
|
8
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class ClearCommandProvider {
|
|
2
|
+
id = '@jupyterlite/ai:clear-command';
|
|
3
|
+
async listCommandCompletions(inputModel) {
|
|
4
|
+
const match = inputModel.currentWord?.match(this._regex)?.[0];
|
|
5
|
+
if (!match) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
if (this._command.name.startsWith(match)) {
|
|
9
|
+
return [this._command];
|
|
10
|
+
}
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
async onSubmit(inputModel) {
|
|
14
|
+
const trimmed = inputModel.value.trim();
|
|
15
|
+
if (trimmed !== this._command.name) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const context = inputModel.chatContext;
|
|
19
|
+
context?.clearMessages?.();
|
|
20
|
+
inputModel.value = '';
|
|
21
|
+
inputModel.clearAttachments();
|
|
22
|
+
inputModel.clearMentions();
|
|
23
|
+
}
|
|
24
|
+
_command = {
|
|
25
|
+
name: '/clear',
|
|
26
|
+
providerId: this.id,
|
|
27
|
+
description: 'Clear the current chat history'
|
|
28
|
+
};
|
|
29
|
+
_regex = /^\/\w*$/;
|
|
30
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ChatCommand, IChatCommandProvider, IInputModel } from '@jupyter/chat';
|
|
2
|
+
import { CommandRegistry } from '@lumino/commands';
|
|
3
|
+
import { ISkillRegistry } from '../tokens';
|
|
4
|
+
export declare class SkillsCommandProvider implements IChatCommandProvider {
|
|
5
|
+
constructor(options: SkillsCommandProvider.IOptions);
|
|
6
|
+
id: string;
|
|
7
|
+
listCommandCompletions(inputModel: IInputModel): Promise<ChatCommand[]>;
|
|
8
|
+
onSubmit(inputModel: IInputModel): Promise<void>;
|
|
9
|
+
private _command;
|
|
10
|
+
private _regex;
|
|
11
|
+
private _commands;
|
|
12
|
+
private _skillRegistry;
|
|
13
|
+
}
|
|
14
|
+
export declare namespace SkillsCommandProvider {
|
|
15
|
+
interface IOptions {
|
|
16
|
+
skillRegistry: ISkillRegistry;
|
|
17
|
+
commands: CommandRegistry;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CommandIds } from '../tokens';
|
|
2
|
+
export class SkillsCommandProvider {
|
|
3
|
+
constructor(options) {
|
|
4
|
+
this._skillRegistry = options.skillRegistry;
|
|
5
|
+
this._commands = options.commands;
|
|
6
|
+
}
|
|
7
|
+
id = '@jupyterlite/ai:skills-command';
|
|
8
|
+
async listCommandCompletions(inputModel) {
|
|
9
|
+
const match = inputModel.currentWord?.match(this._regex)?.[0];
|
|
10
|
+
if (!match) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
if (this._command.name.startsWith(match)) {
|
|
14
|
+
return [this._command];
|
|
15
|
+
}
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
async onSubmit(inputModel) {
|
|
19
|
+
const trimmed = inputModel.value.trim();
|
|
20
|
+
const match = trimmed.match(/^\/skills(?:\s+(.+))?$/);
|
|
21
|
+
if (!match) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Refresh skills from disk before listing
|
|
25
|
+
if (this._commands.hasCommand(CommandIds.refreshSkills)) {
|
|
26
|
+
await this._commands.execute(CommandIds.refreshSkills);
|
|
27
|
+
}
|
|
28
|
+
const query = match[1]?.trim();
|
|
29
|
+
const filtered = this._skillRegistry.listSkills(query);
|
|
30
|
+
let body = '';
|
|
31
|
+
if (filtered.length === 0) {
|
|
32
|
+
body = query
|
|
33
|
+
? `No skills found matching "${query}".`
|
|
34
|
+
: 'No skills are currently registered.';
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const heading = query
|
|
38
|
+
? `Skills matching "${query}" (${filtered.length}):`
|
|
39
|
+
: `Available skills (${filtered.length}):`;
|
|
40
|
+
const lines = filtered.map(skill => `- \`${skill.name}\` — ${skill.description}`);
|
|
41
|
+
body = [heading, '', ...lines].join('\n');
|
|
42
|
+
}
|
|
43
|
+
const context = inputModel.chatContext;
|
|
44
|
+
context?.addSystemMessage?.(body);
|
|
45
|
+
inputModel.value = '';
|
|
46
|
+
inputModel.clearAttachments();
|
|
47
|
+
inputModel.clearMentions();
|
|
48
|
+
}
|
|
49
|
+
_command = {
|
|
50
|
+
name: '/skills',
|
|
51
|
+
providerId: this.id,
|
|
52
|
+
description: 'List available skills'
|
|
53
|
+
};
|
|
54
|
+
_regex = /^\/\w*$/;
|
|
55
|
+
_commands;
|
|
56
|
+
_skillRegistry;
|
|
57
|
+
}
|
package/lib/chat-model.d.ts
CHANGED
|
@@ -48,6 +48,10 @@ export declare class AIChatModel extends AbstractChatModel {
|
|
|
48
48
|
* Clears all messages from the chat and resets conversation state.
|
|
49
49
|
*/
|
|
50
50
|
clearMessages: () => void;
|
|
51
|
+
/**
|
|
52
|
+
* Adds a non-user message to the chat (used by chat commands).
|
|
53
|
+
*/
|
|
54
|
+
addSystemMessage(body: string): void;
|
|
51
55
|
/**
|
|
52
56
|
* Sends a message to the AI and generates a response.
|
|
53
57
|
* @param message The user message to send
|
|
@@ -184,6 +188,10 @@ export declare namespace AIChatModel {
|
|
|
184
188
|
* The clear messages callback.
|
|
185
189
|
*/
|
|
186
190
|
clearMessages: () => void;
|
|
191
|
+
/**
|
|
192
|
+
* Adds an assistant/system message to the chat.
|
|
193
|
+
*/
|
|
194
|
+
addSystemMessage: (body: string) => void;
|
|
187
195
|
/**
|
|
188
196
|
* The agent manager of the chat.
|
|
189
197
|
*/
|
package/lib/chat-model.js
CHANGED
|
@@ -76,7 +76,8 @@ export class AIChatModel extends AbstractChatModel {
|
|
|
76
76
|
messages: this.messages,
|
|
77
77
|
stopStreaming: () => this.stopStreaming(),
|
|
78
78
|
clearMessages: () => this.clearMessages(),
|
|
79
|
-
agentManager: this._agentManager
|
|
79
|
+
agentManager: this._agentManager,
|
|
80
|
+
addSystemMessage: (body) => this.addSystemMessage(body)
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
83
|
/**
|
|
@@ -93,11 +94,30 @@ export class AIChatModel extends AbstractChatModel {
|
|
|
93
94
|
this._toolContexts.clear();
|
|
94
95
|
this._agentManager.clearHistory();
|
|
95
96
|
};
|
|
97
|
+
/**
|
|
98
|
+
* Adds a non-user message to the chat (used by chat commands).
|
|
99
|
+
*/
|
|
100
|
+
addSystemMessage(body) {
|
|
101
|
+
const message = {
|
|
102
|
+
body,
|
|
103
|
+
sender: this._getAIUser(),
|
|
104
|
+
id: UUID.uuid4(),
|
|
105
|
+
time: Date.now() / 1000,
|
|
106
|
+
type: 'msg',
|
|
107
|
+
raw_time: false
|
|
108
|
+
};
|
|
109
|
+
this.messageAdded(message);
|
|
110
|
+
}
|
|
96
111
|
/**
|
|
97
112
|
* Sends a message to the AI and generates a response.
|
|
98
113
|
* @param message The user message to send
|
|
99
114
|
*/
|
|
100
115
|
async sendMessage(message) {
|
|
116
|
+
const hasBody = message.body.trim().length > 0;
|
|
117
|
+
const hasAttachments = this.input.attachments.length > 0;
|
|
118
|
+
if (!hasBody && !hasAttachments) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
101
121
|
// Add user message to chat
|
|
102
122
|
const userMessage = {
|
|
103
123
|
body: message.body,
|
|
@@ -262,6 +282,19 @@ export class AIChatModel extends AbstractChatModel {
|
|
|
262
282
|
return `query: "${parsedInput.query}"`;
|
|
263
283
|
}
|
|
264
284
|
break;
|
|
285
|
+
case 'discover_skills':
|
|
286
|
+
if (parsedInput.query) {
|
|
287
|
+
return `query: "${parsedInput.query}"`;
|
|
288
|
+
}
|
|
289
|
+
break;
|
|
290
|
+
case 'load_skill':
|
|
291
|
+
if (parsedInput.name) {
|
|
292
|
+
if (parsedInput.resource) {
|
|
293
|
+
return `${parsedInput.name} (${parsedInput.resource})`;
|
|
294
|
+
}
|
|
295
|
+
return parsedInput.name;
|
|
296
|
+
}
|
|
297
|
+
break;
|
|
265
298
|
}
|
|
266
299
|
}
|
|
267
300
|
catch {
|
|
@@ -361,8 +394,7 @@ export class AIChatModel extends AbstractChatModel {
|
|
|
361
394
|
return;
|
|
362
395
|
}
|
|
363
396
|
context.status = status;
|
|
364
|
-
|
|
365
|
-
...existingMessage,
|
|
397
|
+
existingMessage.update({
|
|
366
398
|
body: Private.buildToolCallHtml({
|
|
367
399
|
toolName: context.toolName,
|
|
368
400
|
input: context.input,
|