@jupyterlite/ai 0.12.0 → 0.13.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 +24 -2
- package/lib/agent.js +161 -24
- package/lib/{chat-model-registry.d.ts → chat-model-handler.d.ts} +12 -11
- package/lib/{chat-model-registry.js → chat-model-handler.js} +6 -40
- package/lib/chat-model.d.ts +8 -0
- package/lib/chat-model.js +156 -8
- package/lib/completion/completion-provider.d.ts +1 -1
- package/lib/completion/completion-provider.js +14 -2
- package/lib/components/model-select.js +4 -4
- package/lib/components/tool-select.d.ts +11 -2
- package/lib/components/tool-select.js +77 -18
- package/lib/index.d.ts +3 -3
- package/lib/index.js +128 -66
- package/lib/models/settings-model.d.ts +2 -0
- package/lib/models/settings-model.js +2 -0
- package/lib/providers/built-in-providers.js +7 -0
- package/lib/providers/provider-tools.d.ts +36 -0
- package/lib/providers/provider-tools.js +93 -0
- package/lib/rendered-message-outputarea.d.ts +24 -0
- package/lib/rendered-message-outputarea.js +48 -0
- package/lib/tokens.d.ts +44 -7
- package/lib/tokens.js +1 -1
- package/lib/tools/commands.js +4 -2
- package/lib/tools/web.d.ts +8 -0
- package/lib/tools/web.js +196 -0
- package/lib/widgets/ai-settings.d.ts +1 -1
- package/lib/widgets/ai-settings.js +125 -38
- package/lib/widgets/main-area-chat.d.ts +6 -0
- package/lib/widgets/main-area-chat.js +28 -0
- package/lib/widgets/provider-config-dialog.js +207 -4
- package/package.json +10 -4
- package/schema/settings-model.json +89 -1
- package/src/agent.ts +220 -42
- package/src/{chat-model-registry.ts → chat-model-handler.ts} +16 -51
- package/src/chat-model.ts +223 -14
- package/src/completion/completion-provider.ts +26 -12
- package/src/components/model-select.tsx +4 -5
- package/src/components/tool-select.tsx +110 -7
- package/src/index.ts +153 -82
- package/src/models/settings-model.ts +6 -0
- package/src/providers/built-in-providers.ts +7 -0
- package/src/providers/provider-tools.ts +179 -0
- package/src/rendered-message-outputarea.ts +62 -0
- package/src/tokens.ts +53 -9
- package/src/tools/commands.ts +4 -2
- package/src/tools/web.ts +238 -0
- package/src/widgets/ai-settings.tsx +282 -77
- package/src/widgets/main-area-chat.ts +34 -1
- package/src/widgets/provider-config-dialog.tsx +496 -3
package/lib/agent.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ISignal } from '@lumino/signaling';
|
|
2
2
|
import { type Tool } from 'ai';
|
|
3
3
|
import { ISecretsManager } from 'jupyter-secrets-manager';
|
|
4
|
+
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
4
5
|
import { AISettingsModel } from './models/settings-model';
|
|
5
6
|
import type { IProviderRegistry } from './tokens';
|
|
6
7
|
import { ISkillRegistry, ITool, IToolRegistry, ITokenUsage } from './tokens';
|
|
@@ -22,7 +23,7 @@ export declare namespace AgentManagerFactory {
|
|
|
22
23
|
/**
|
|
23
24
|
* The token used to request the secrets manager.
|
|
24
25
|
*/
|
|
25
|
-
token: symbol;
|
|
26
|
+
token: symbol | null;
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
export declare class AgentManagerFactory {
|
|
@@ -92,7 +93,7 @@ export interface IAgentEventTypeMap {
|
|
|
92
93
|
tool_call_complete: {
|
|
93
94
|
callId: string;
|
|
94
95
|
toolName: string;
|
|
95
|
-
|
|
96
|
+
outputData: unknown;
|
|
96
97
|
isError: boolean;
|
|
97
98
|
};
|
|
98
99
|
tool_approval_request: {
|
|
@@ -148,6 +149,10 @@ export interface IAgentManagerOptions {
|
|
|
148
149
|
* Initial token usage.
|
|
149
150
|
*/
|
|
150
151
|
tokenUsage?: ITokenUsage;
|
|
152
|
+
/**
|
|
153
|
+
* JupyterLab render mime registry for discovering supported MIME types.
|
|
154
|
+
*/
|
|
155
|
+
renderMimeRegistry?: IRenderMimeRegistry;
|
|
151
156
|
}
|
|
152
157
|
/**
|
|
153
158
|
* Manages the AI agent lifecycle and execution loop.
|
|
@@ -245,6 +250,10 @@ export declare class AgentManager {
|
|
|
245
250
|
* Prepare model, tools, and settings needed to (re)build the agent.
|
|
246
251
|
*/
|
|
247
252
|
private _prepareAgentConfig;
|
|
253
|
+
/**
|
|
254
|
+
* Build the runtime tool map used by the agent.
|
|
255
|
+
*/
|
|
256
|
+
private _buildRuntimeTools;
|
|
248
257
|
/**
|
|
249
258
|
* Rebuild the agent using cached resources and the current skills snapshot.
|
|
250
259
|
*/
|
|
@@ -264,6 +273,14 @@ export declare class AgentManager {
|
|
|
264
273
|
* Handles tool-result stream parts.
|
|
265
274
|
*/
|
|
266
275
|
private _handleToolResult;
|
|
276
|
+
/**
|
|
277
|
+
* Handles tool-error stream parts.
|
|
278
|
+
*/
|
|
279
|
+
private _handleToolError;
|
|
280
|
+
/**
|
|
281
|
+
* Handles tool-output-denied stream parts.
|
|
282
|
+
*/
|
|
283
|
+
private _handleToolOutputDenied;
|
|
267
284
|
/**
|
|
268
285
|
* Handles tool-approval-request stream parts.
|
|
269
286
|
*/
|
|
@@ -296,6 +313,10 @@ export declare class AgentManager {
|
|
|
296
313
|
* @returns The enhanced system prompt with dynamic additions
|
|
297
314
|
*/
|
|
298
315
|
private _getEnhancedSystemPrompt;
|
|
316
|
+
/**
|
|
317
|
+
* Build an instruction line describing MIME types supported by this session.
|
|
318
|
+
*/
|
|
319
|
+
private _getSupportedMimeTypesInstruction;
|
|
299
320
|
private _settingsModel;
|
|
300
321
|
private _toolRegistry?;
|
|
301
322
|
private _providerRegistry?;
|
|
@@ -312,6 +333,7 @@ export declare class AgentManager {
|
|
|
312
333
|
private _activeProvider;
|
|
313
334
|
private _activeProviderChanged;
|
|
314
335
|
private _skills;
|
|
336
|
+
private _renderMimeRegistry?;
|
|
315
337
|
private _initQueue;
|
|
316
338
|
private _agentConfig;
|
|
317
339
|
private _pendingApprovals;
|
package/lib/agent.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Signal } from '@lumino/signaling';
|
|
|
2
2
|
import { ToolLoopAgent, stepCountIs } from 'ai';
|
|
3
3
|
import { createMCPClient } from '@ai-sdk/mcp';
|
|
4
4
|
import { createModel } from './providers/models';
|
|
5
|
+
import { createProviderTools } from './providers/provider-tools';
|
|
5
6
|
import { SECRETS_NAMESPACE } from './tokens';
|
|
6
7
|
export class AgentManagerFactory {
|
|
7
8
|
constructor(options) {
|
|
@@ -20,6 +21,10 @@ export class AgentManagerFactory {
|
|
|
20
21
|
this._initializeAgents().catch(error => console.warn('Failed to initialize agent in constructor:', error));
|
|
21
22
|
// Listen for settings changes
|
|
22
23
|
this._settingsModel.stateChanged.connect(this._onSettingsChanged, this);
|
|
24
|
+
// Disable the secrets manager if the token is empty.
|
|
25
|
+
if (!options.token) {
|
|
26
|
+
this._secretsManager = undefined;
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
createAgent(options) {
|
|
25
30
|
const agentManager = new AgentManager({
|
|
@@ -180,6 +185,7 @@ export class AgentManager {
|
|
|
180
185
|
this._tokenUsageChanged = new Signal(this);
|
|
181
186
|
this._skills = [];
|
|
182
187
|
this._agentConfig = null;
|
|
188
|
+
this._renderMimeRegistry = options.renderMimeRegistry;
|
|
183
189
|
this.activeProvider =
|
|
184
190
|
options.activeProvider ?? this._settingsModel.config.defaultProvider;
|
|
185
191
|
// Initialize selected tools to all available tools by default
|
|
@@ -372,7 +378,7 @@ export class AgentManager {
|
|
|
372
378
|
this._updateTokenUsage(await result.usage);
|
|
373
379
|
// Add response messages to history
|
|
374
380
|
if (responseMessages.messages?.length) {
|
|
375
|
-
this._history.push(...responseMessages.messages);
|
|
381
|
+
this._history.push(...Private.sanitizeModelMessages(responseMessages.messages));
|
|
376
382
|
}
|
|
377
383
|
// Add approval response if processed
|
|
378
384
|
if (streamResult.approvalResponse) {
|
|
@@ -454,18 +460,27 @@ export class AgentManager {
|
|
|
454
460
|
this._mcpTools = mcpTools;
|
|
455
461
|
}
|
|
456
462
|
const model = await this._createModel();
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
: this._mcpTools;
|
|
463
|
+
const supportsToolCalling = this._supportsToolCalling();
|
|
464
|
+
const canUseTools = config.toolsEnabled && supportsToolCalling;
|
|
465
|
+
const hasFunctionToolRegistry = !!(this._toolRegistry && Object.keys(this._toolRegistry.tools).length > 0);
|
|
466
|
+
const selectedFunctionTools = canUseTools && hasFunctionToolRegistry ? this.selectedAgentTools : {};
|
|
467
|
+
const functionTools = canUseTools
|
|
468
|
+
? { ...selectedFunctionTools, ...this._mcpTools }
|
|
469
|
+
: {};
|
|
465
470
|
const activeProviderConfig = this._settingsModel.getProvider(this._activeProvider);
|
|
471
|
+
const activeProviderInfo = activeProviderConfig && this._providerRegistry
|
|
472
|
+
? this._providerRegistry.getProviderInfo(activeProviderConfig.provider)
|
|
473
|
+
: null;
|
|
466
474
|
const temperature = activeProviderConfig?.parameters?.temperature ?? DEFAULT_TEMPERATURE;
|
|
467
475
|
const maxTokens = activeProviderConfig?.parameters?.maxOutputTokens;
|
|
468
476
|
const maxTurns = activeProviderConfig?.parameters?.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
477
|
+
const tools = this._buildRuntimeTools({
|
|
478
|
+
providerInfo: activeProviderInfo,
|
|
479
|
+
customSettings: activeProviderConfig?.customSettings,
|
|
480
|
+
functionTools,
|
|
481
|
+
includeProviderTools: canUseTools
|
|
482
|
+
});
|
|
483
|
+
const shouldUseTools = canUseTools && Object.keys(tools).length > 0;
|
|
469
484
|
this._agentConfig = {
|
|
470
485
|
model,
|
|
471
486
|
tools,
|
|
@@ -476,6 +491,22 @@ export class AgentManager {
|
|
|
476
491
|
shouldUseTools
|
|
477
492
|
};
|
|
478
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* Build the runtime tool map used by the agent.
|
|
496
|
+
*/
|
|
497
|
+
_buildRuntimeTools(options) {
|
|
498
|
+
const providerTools = options.includeProviderTools
|
|
499
|
+
? createProviderTools({
|
|
500
|
+
providerInfo: options.providerInfo,
|
|
501
|
+
customSettings: options.customSettings,
|
|
502
|
+
hasFunctionTools: Object.keys(options.functionTools).length > 0
|
|
503
|
+
})
|
|
504
|
+
: {};
|
|
505
|
+
return {
|
|
506
|
+
...providerTools,
|
|
507
|
+
...options.functionTools
|
|
508
|
+
};
|
|
509
|
+
}
|
|
479
510
|
/**
|
|
480
511
|
* Rebuild the agent using cached resources and the current skills snapshot.
|
|
481
512
|
*/
|
|
@@ -485,9 +516,21 @@ export class AgentManager {
|
|
|
485
516
|
return;
|
|
486
517
|
}
|
|
487
518
|
const { model, tools, temperature, maxOutputTokens, maxTurns, baseSystemPrompt, shouldUseTools } = this._agentConfig;
|
|
488
|
-
const
|
|
489
|
-
? this._getEnhancedSystemPrompt(baseSystemPrompt)
|
|
519
|
+
const baseInstructions = shouldUseTools
|
|
520
|
+
? this._getEnhancedSystemPrompt(baseSystemPrompt, tools)
|
|
490
521
|
: baseSystemPrompt || 'You are a helpful assistant.';
|
|
522
|
+
const richOutputWorkflowInstruction = shouldUseTools
|
|
523
|
+
? '- When the user asks for visual or rich outputs, prefer running code/commands that produce those outputs and describe that they will be rendered in chat.'
|
|
524
|
+
: '- When tools are unavailable, explain the limitation clearly and provide concrete steps the user can run to produce the desired rich outputs.';
|
|
525
|
+
const supportedMimeTypesInstruction = this._getSupportedMimeTypesInstruction();
|
|
526
|
+
const instructions = `${baseInstructions}
|
|
527
|
+
|
|
528
|
+
RICH OUTPUT RENDERING:
|
|
529
|
+
- The chat UI can render rich MIME outputs as separate assistant messages.
|
|
530
|
+
- ${supportedMimeTypesInstruction}
|
|
531
|
+
- Use only MIME types from the supported list when creating MIME bundles. Do not invent MIME keys.
|
|
532
|
+
- Do not claim that you cannot display maps, images, or rich outputs in chat.
|
|
533
|
+
${richOutputWorkflowInstruction}`;
|
|
491
534
|
this._agent = new ToolLoopAgent({
|
|
492
535
|
model,
|
|
493
536
|
instructions,
|
|
@@ -546,6 +589,12 @@ export class AgentManager {
|
|
|
546
589
|
case 'tool-result':
|
|
547
590
|
this._handleToolResult(part);
|
|
548
591
|
break;
|
|
592
|
+
case 'tool-error':
|
|
593
|
+
this._handleToolError(part);
|
|
594
|
+
break;
|
|
595
|
+
case 'tool-output-denied':
|
|
596
|
+
this._handleToolOutputDenied(part);
|
|
597
|
+
break;
|
|
549
598
|
case 'tool-approval-request':
|
|
550
599
|
// Complete current message before approval
|
|
551
600
|
if (currentMessageId && fullResponse) {
|
|
@@ -579,9 +628,6 @@ export class AgentManager {
|
|
|
579
628
|
* Handles tool-result stream parts.
|
|
580
629
|
*/
|
|
581
630
|
_handleToolResult(part) {
|
|
582
|
-
const output = typeof part.output === 'string'
|
|
583
|
-
? part.output
|
|
584
|
-
: JSON.stringify(part.output, null, 2);
|
|
585
631
|
const isError = typeof part.output === 'object' &&
|
|
586
632
|
part.output !== null &&
|
|
587
633
|
'success' in part.output &&
|
|
@@ -591,11 +637,44 @@ export class AgentManager {
|
|
|
591
637
|
data: {
|
|
592
638
|
callId: part.toolCallId,
|
|
593
639
|
toolName: part.toolName,
|
|
594
|
-
output,
|
|
640
|
+
outputData: part.output,
|
|
595
641
|
isError
|
|
596
642
|
}
|
|
597
643
|
});
|
|
598
644
|
}
|
|
645
|
+
/**
|
|
646
|
+
* Handles tool-error stream parts.
|
|
647
|
+
*/
|
|
648
|
+
_handleToolError(part) {
|
|
649
|
+
const output = typeof part.error === 'string'
|
|
650
|
+
? part.error
|
|
651
|
+
: part.error instanceof Error
|
|
652
|
+
? part.error.message
|
|
653
|
+
: JSON.stringify(part.error, null, 2);
|
|
654
|
+
this._agentEvent.emit({
|
|
655
|
+
type: 'tool_call_complete',
|
|
656
|
+
data: {
|
|
657
|
+
callId: part.toolCallId,
|
|
658
|
+
toolName: part.toolName,
|
|
659
|
+
outputData: output,
|
|
660
|
+
isError: true
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Handles tool-output-denied stream parts.
|
|
666
|
+
*/
|
|
667
|
+
_handleToolOutputDenied(part) {
|
|
668
|
+
this._agentEvent.emit({
|
|
669
|
+
type: 'tool_call_complete',
|
|
670
|
+
data: {
|
|
671
|
+
callId: part.toolCallId,
|
|
672
|
+
toolName: part.toolName,
|
|
673
|
+
outputData: 'Tool output was denied.',
|
|
674
|
+
isError: true
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
}
|
|
599
678
|
/**
|
|
600
679
|
* Handles tool-approval-request stream parts.
|
|
601
680
|
*/
|
|
@@ -681,8 +760,16 @@ export class AgentManager {
|
|
|
681
760
|
const baseURL = activeProviderConfig.baseURL;
|
|
682
761
|
let apiKey;
|
|
683
762
|
if (this._secretsManager && this._settingsModel.config.useSecretsManager) {
|
|
684
|
-
|
|
685
|
-
|
|
763
|
+
const token = Private.getToken();
|
|
764
|
+
if (!token) {
|
|
765
|
+
// This should never happen, the secrets manager should be disabled.
|
|
766
|
+
console.error('@jupyterlite/ai::AgentManager error: the settings manager token is not set.\nYou should disable the the secrets manager from the AI settings.');
|
|
767
|
+
apiKey = '';
|
|
768
|
+
}
|
|
769
|
+
else {
|
|
770
|
+
apiKey =
|
|
771
|
+
(await this._secretsManager.get(token, SECRETS_NAMESPACE, `${provider}:apiKey`))?.value ?? '';
|
|
772
|
+
}
|
|
686
773
|
}
|
|
687
774
|
else {
|
|
688
775
|
apiKey = this._settingsModel.getApiKey(activeProviderConfig.id);
|
|
@@ -699,12 +786,11 @@ export class AgentManager {
|
|
|
699
786
|
* @param baseSystemPrompt The base system prompt from settings
|
|
700
787
|
* @returns The enhanced system prompt with dynamic additions
|
|
701
788
|
*/
|
|
702
|
-
_getEnhancedSystemPrompt(baseSystemPrompt) {
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
const skillsPrompt = `
|
|
789
|
+
_getEnhancedSystemPrompt(baseSystemPrompt, tools) {
|
|
790
|
+
let prompt = baseSystemPrompt;
|
|
791
|
+
if (this._skills.length > 0) {
|
|
792
|
+
const lines = this._skills.map(skill => `- ${skill.name}: ${skill.description}`);
|
|
793
|
+
const skillsPrompt = `
|
|
708
794
|
|
|
709
795
|
AGENT SKILLS:
|
|
710
796
|
Skills are provided via the skills registry and accessed through tools (not commands).
|
|
@@ -716,7 +802,41 @@ If the load_skill result includes a non-empty "resources" array, those are bundl
|
|
|
716
802
|
AVAILABLE SKILLS (preloaded snapshot):
|
|
717
803
|
${lines.join('\n')}
|
|
718
804
|
`;
|
|
719
|
-
|
|
805
|
+
prompt += skillsPrompt;
|
|
806
|
+
}
|
|
807
|
+
const toolNames = new Set(Object.keys(tools));
|
|
808
|
+
const hasBrowserFetch = toolNames.has('browser_fetch');
|
|
809
|
+
const hasWebFetch = toolNames.has('web_fetch');
|
|
810
|
+
const hasWebSearch = toolNames.has('web_search');
|
|
811
|
+
if (hasBrowserFetch || hasWebFetch || hasWebSearch) {
|
|
812
|
+
const webRetrievalPrompt = `
|
|
813
|
+
|
|
814
|
+
WEB RETRIEVAL POLICY:
|
|
815
|
+
- If the user asks about a specific URL and browser_fetch is available, call browser_fetch first for that URL.
|
|
816
|
+
- If browser_fetch fails due to CORS/network/access, try web_fetch (if available) for that same URL.
|
|
817
|
+
- If web_fetch fails with access/policy errors (for example: url_not_accessible or url_not_allowed) and browser_fetch is available, you MUST call browser_fetch for that same URL before searching.
|
|
818
|
+
- If either fetch method fails with temporary access/network issues (for example: network_or_cors), try the other fetch method if available before searching.
|
|
819
|
+
- Only fall back to web_search after both fetch methods fail or are unavailable.
|
|
820
|
+
- If the user explicitly asks to inspect one exact URL, do not skip directly to search unless both fetch methods fail or are unavailable.
|
|
821
|
+
- In your final response, state which retrieval method succeeded (browser_fetch, web_fetch, or web_search) and mention relevant limitations.
|
|
822
|
+
`;
|
|
823
|
+
prompt += webRetrievalPrompt;
|
|
824
|
+
}
|
|
825
|
+
return prompt;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Build an instruction line describing MIME types supported by this session.
|
|
829
|
+
*/
|
|
830
|
+
_getSupportedMimeTypesInstruction() {
|
|
831
|
+
const mimeTypes = this._renderMimeRegistry?.mimeTypes ?? [];
|
|
832
|
+
const safeMimeTypes = mimeTypes.filter(mimeType => {
|
|
833
|
+
const factory = this._renderMimeRegistry?.getFactory(mimeType);
|
|
834
|
+
return !!factory?.safe;
|
|
835
|
+
});
|
|
836
|
+
if (safeMimeTypes.length === 0) {
|
|
837
|
+
return 'Supported MIME types are determined by the active JupyterLab renderers in this session.';
|
|
838
|
+
}
|
|
839
|
+
return `Supported MIME types in this session: ${safeMimeTypes.join(', ')}`;
|
|
720
840
|
}
|
|
721
841
|
// Private attributes
|
|
722
842
|
_settingsModel;
|
|
@@ -735,12 +855,29 @@ ${lines.join('\n')}
|
|
|
735
855
|
_activeProvider = '';
|
|
736
856
|
_activeProviderChanged = new Signal(this);
|
|
737
857
|
_skills;
|
|
858
|
+
_renderMimeRegistry;
|
|
738
859
|
_initQueue = Promise.resolve();
|
|
739
860
|
_agentConfig;
|
|
740
861
|
_pendingApprovals = new Map();
|
|
741
862
|
}
|
|
742
863
|
var Private;
|
|
743
864
|
(function (Private) {
|
|
865
|
+
/**
|
|
866
|
+
* Keep only serializable messages by doing a JSON round-trip.
|
|
867
|
+
* Messages that cannot be serialized are dropped.
|
|
868
|
+
*/
|
|
869
|
+
Private.sanitizeModelMessages = (messages) => {
|
|
870
|
+
const sanitized = [];
|
|
871
|
+
for (const message of messages) {
|
|
872
|
+
try {
|
|
873
|
+
sanitized.push(JSON.parse(JSON.stringify(message)));
|
|
874
|
+
}
|
|
875
|
+
catch {
|
|
876
|
+
// Drop messages that cannot be serialized
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
return sanitized;
|
|
880
|
+
};
|
|
744
881
|
/**
|
|
745
882
|
* The token to use with the secrets manager, setter and getter.
|
|
746
883
|
*/
|
|
@@ -3,33 +3,30 @@ import { TranslationBundle } from '@jupyterlab/translation';
|
|
|
3
3
|
import { AgentManagerFactory } from './agent';
|
|
4
4
|
import { AIChatModel } from './chat-model';
|
|
5
5
|
import { AISettingsModel } from './models/settings-model';
|
|
6
|
-
import {
|
|
6
|
+
import { IChatModelHandler, IProviderRegistry, ITokenUsage, IToolRegistry } from './tokens';
|
|
7
7
|
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
8
|
+
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
8
9
|
/**
|
|
9
|
-
* The chat model
|
|
10
|
+
* The chat model handler.
|
|
10
11
|
*/
|
|
11
|
-
export declare class
|
|
12
|
-
constructor(options:
|
|
13
|
-
createModel(name
|
|
14
|
-
add(model: AIChatModel): void;
|
|
15
|
-
get(name: string): AIChatModel | undefined;
|
|
16
|
-
getAll(): AIChatModel[];
|
|
17
|
-
remove(name: string): void;
|
|
12
|
+
export declare class ChatModelHandler implements IChatModelHandler {
|
|
13
|
+
constructor(options: ChatModelHandler.IOptions);
|
|
14
|
+
createModel(name: string, activeProvider: string, tokenUsage?: ITokenUsage): AIChatModel;
|
|
18
15
|
/**
|
|
19
16
|
* Getter/setter for the active cell manager.
|
|
20
17
|
*/
|
|
21
18
|
get activeCellManager(): ActiveCellManager | undefined;
|
|
22
19
|
set activeCellManager(manager: ActiveCellManager | undefined);
|
|
23
|
-
private _models;
|
|
24
20
|
private _docManager;
|
|
25
21
|
private _agentManagerFactory;
|
|
26
22
|
private _settingsModel;
|
|
27
23
|
private _toolRegistry?;
|
|
28
24
|
private _providerRegistry?;
|
|
25
|
+
private _rmRegistry;
|
|
29
26
|
private _activeCellManager?;
|
|
30
27
|
private _trans;
|
|
31
28
|
}
|
|
32
|
-
export declare namespace
|
|
29
|
+
export declare namespace ChatModelHandler {
|
|
33
30
|
interface IOptions {
|
|
34
31
|
/**
|
|
35
32
|
* The document manager.
|
|
@@ -51,6 +48,10 @@ export declare namespace ChatModelRegistry {
|
|
|
51
48
|
* Optional provider registry for model creation
|
|
52
49
|
*/
|
|
53
50
|
providerRegistry?: IProviderRegistry;
|
|
51
|
+
/**
|
|
52
|
+
* Render mime registry.
|
|
53
|
+
*/
|
|
54
|
+
rmRegistry: IRenderMimeRegistry;
|
|
54
55
|
/**
|
|
55
56
|
* The active cell manager.
|
|
56
57
|
*/
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { AIChatModel } from './chat-model';
|
|
2
|
-
import { UUID } from '@lumino/coreutils';
|
|
3
2
|
/**
|
|
4
|
-
* The chat model
|
|
3
|
+
* The chat model handler.
|
|
5
4
|
*/
|
|
6
|
-
export class
|
|
5
|
+
export class ChatModelHandler {
|
|
7
6
|
constructor(options) {
|
|
8
7
|
this._docManager = options.docManager;
|
|
9
8
|
this._agentManagerFactory = options.agentManagerFactory;
|
|
10
9
|
this._settingsModel = options.settingsModel;
|
|
11
10
|
this._toolRegistry = options.toolRegistry;
|
|
12
11
|
this._providerRegistry = options.providerRegistry;
|
|
12
|
+
this._rmRegistry = options.rmRegistry;
|
|
13
13
|
this._activeCellManager = options.activeCellManager;
|
|
14
14
|
this._trans = options.trans;
|
|
15
15
|
}
|
|
@@ -20,7 +20,8 @@ export class ChatModelRegistry {
|
|
|
20
20
|
toolRegistry: this._toolRegistry,
|
|
21
21
|
providerRegistry: this._providerRegistry,
|
|
22
22
|
activeProvider,
|
|
23
|
-
tokenUsage
|
|
23
|
+
tokenUsage,
|
|
24
|
+
renderMimeRegistry: this._rmRegistry
|
|
24
25
|
});
|
|
25
26
|
// Create AI chat model
|
|
26
27
|
const model = new AIChatModel({
|
|
@@ -31,44 +32,9 @@ export class ChatModelRegistry {
|
|
|
31
32
|
documentManager: this._docManager,
|
|
32
33
|
trans: this._trans
|
|
33
34
|
});
|
|
34
|
-
// Set the name of the chat if not provided.
|
|
35
|
-
// The name will be the name set by the user to the model if not already used by
|
|
36
|
-
// another chat.
|
|
37
|
-
if (!name || this._models.findIndex(m => m.name === name) !== -1) {
|
|
38
|
-
const existingName = this.getAll().map(model => model.name);
|
|
39
|
-
const modelName = this._settingsModel.getProvider(agentManager.activeProvider)?.name ||
|
|
40
|
-
UUID.uuid4();
|
|
41
|
-
name = modelName;
|
|
42
|
-
let i = 1;
|
|
43
|
-
while (existingName.includes(name)) {
|
|
44
|
-
name = `${modelName}-${i}`;
|
|
45
|
-
i += 1;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
35
|
model.name = name;
|
|
49
|
-
this.add(model);
|
|
50
36
|
return model;
|
|
51
37
|
}
|
|
52
|
-
add(model) {
|
|
53
|
-
if (!this._models.find(m => m.name === model.name)) {
|
|
54
|
-
this._models.push(model);
|
|
55
|
-
model.disposed.connect(() => {
|
|
56
|
-
this.remove(model.name);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
get(name) {
|
|
61
|
-
return this._models.find(m => m.name === name);
|
|
62
|
-
}
|
|
63
|
-
getAll() {
|
|
64
|
-
return this._models;
|
|
65
|
-
}
|
|
66
|
-
remove(name) {
|
|
67
|
-
const index = this._models.findIndex(m => m.name === name);
|
|
68
|
-
if (index !== -1) {
|
|
69
|
-
this._models.splice(index, 1);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
38
|
/**
|
|
73
39
|
* Getter/setter for the active cell manager.
|
|
74
40
|
*/
|
|
@@ -78,12 +44,12 @@ export class ChatModelRegistry {
|
|
|
78
44
|
set activeCellManager(manager) {
|
|
79
45
|
this._activeCellManager = manager;
|
|
80
46
|
}
|
|
81
|
-
_models = [];
|
|
82
47
|
_docManager;
|
|
83
48
|
_agentManagerFactory;
|
|
84
49
|
_settingsModel;
|
|
85
50
|
_toolRegistry;
|
|
86
51
|
_providerRegistry;
|
|
52
|
+
_rmRegistry;
|
|
87
53
|
_activeCellManager;
|
|
88
54
|
_trans;
|
|
89
55
|
}
|
package/lib/chat-model.d.ts
CHANGED
|
@@ -92,6 +92,10 @@ export declare class AIChatModel extends AbstractChatModel {
|
|
|
92
92
|
* @returns A short summary string or empty string if none available
|
|
93
93
|
*/
|
|
94
94
|
private _extractToolSummary;
|
|
95
|
+
/**
|
|
96
|
+
* Determine whether this tool call should auto-render trusted MIME bundles.
|
|
97
|
+
*/
|
|
98
|
+
private _computeShouldAutoRenderMimeBundles;
|
|
95
99
|
/**
|
|
96
100
|
* Handles the start of a tool call execution.
|
|
97
101
|
* @param event Event containing the tool call start data
|
|
@@ -101,6 +105,10 @@ export declare class AIChatModel extends AbstractChatModel {
|
|
|
101
105
|
* Handles the completion of a tool call execution.
|
|
102
106
|
*/
|
|
103
107
|
private _handleToolCallCompleteEvent;
|
|
108
|
+
/**
|
|
109
|
+
* Determine whether a tool call output should auto-render MIME bundles.
|
|
110
|
+
*/
|
|
111
|
+
private _shouldAutoRenderMimeBundles;
|
|
104
112
|
/**
|
|
105
113
|
* Handles error events from the AI agent.
|
|
106
114
|
*/
|