@jupyterlite/ai 0.17.0 → 0.19.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.
Files changed (114) hide show
  1. package/lib/chat-commands/clear.d.ts +1 -0
  2. package/lib/chat-commands/index.d.ts +1 -0
  3. package/lib/chat-commands/skills.d.ts +2 -1
  4. package/lib/chat-model-handler.d.ts +4 -3
  5. package/lib/chat-model-handler.js +2 -1
  6. package/lib/chat-model.d.ts +148 -8
  7. package/lib/chat-model.js +368 -79
  8. package/lib/completion/completion-provider.d.ts +3 -1
  9. package/lib/completion/completion-provider.js +1 -2
  10. package/lib/completion/index.d.ts +1 -0
  11. package/lib/components/clear-button.d.ts +1 -0
  12. package/lib/components/clear-button.js +3 -4
  13. package/lib/components/completion-status.d.ts +1 -0
  14. package/lib/components/completion-status.js +5 -4
  15. package/lib/components/index.d.ts +1 -0
  16. package/lib/components/model-select.d.ts +1 -0
  17. package/lib/components/model-select.js +62 -67
  18. package/lib/components/save-button.d.ts +3 -2
  19. package/lib/components/save-button.js +4 -5
  20. package/lib/components/stop-button.d.ts +1 -0
  21. package/lib/components/stop-button.js +3 -4
  22. package/lib/components/tool-select.d.ts +3 -1
  23. package/lib/components/tool-select.js +47 -60
  24. package/lib/components/usage-display.d.ts +4 -2
  25. package/lib/components/usage-display.js +50 -61
  26. package/lib/diff-manager.d.ts +3 -1
  27. package/lib/index.d.ts +3 -2
  28. package/lib/index.js +50 -59
  29. package/lib/models/settings-model.d.ts +3 -1
  30. package/lib/models/settings-model.js +1 -0
  31. package/lib/rendered-message-outputarea.d.ts +1 -0
  32. package/lib/tokens.d.ts +48 -597
  33. package/lib/tokens.js +2 -31
  34. package/lib/widgets/ai-settings.d.ts +3 -1
  35. package/lib/widgets/ai-settings.js +185 -344
  36. package/lib/widgets/main-area-chat.d.ts +3 -3
  37. package/lib/widgets/main-area-chat.js +2 -4
  38. package/lib/widgets/provider-config-dialog.d.ts +2 -1
  39. package/lib/widgets/provider-config-dialog.js +102 -167
  40. package/package.json +111 -258
  41. package/schema/settings-model.json +6 -0
  42. package/src/chat-commands/skills.ts +2 -2
  43. package/src/chat-model-handler.ts +10 -6
  44. package/src/chat-model.ts +488 -96
  45. package/src/completion/completion-provider.ts +6 -6
  46. package/src/components/clear-button.tsx +0 -2
  47. package/src/components/completion-status.tsx +2 -2
  48. package/src/components/model-select.tsx +1 -1
  49. package/src/components/save-button.tsx +3 -3
  50. package/src/components/stop-button.tsx +0 -2
  51. package/src/components/tool-select.tsx +10 -9
  52. package/src/components/usage-display.tsx +4 -2
  53. package/src/diff-manager.ts +4 -3
  54. package/src/index.ts +103 -107
  55. package/src/models/settings-model.ts +7 -6
  56. package/src/tokens.ts +54 -744
  57. package/src/widgets/ai-settings.tsx +40 -11
  58. package/src/widgets/main-area-chat.ts +5 -8
  59. package/src/widgets/provider-config-dialog.tsx +8 -8
  60. package/LICENSE +0 -30
  61. package/README.md +0 -49
  62. package/lib/agent.d.ts +0 -277
  63. package/lib/agent.js +0 -1116
  64. package/lib/icons.d.ts +0 -3
  65. package/lib/icons.js +0 -8
  66. package/lib/providers/built-in-providers.d.ts +0 -21
  67. package/lib/providers/built-in-providers.js +0 -233
  68. package/lib/providers/generated-context-windows.d.ts +0 -8
  69. package/lib/providers/generated-context-windows.js +0 -96
  70. package/lib/providers/model-info.d.ts +0 -3
  71. package/lib/providers/model-info.js +0 -58
  72. package/lib/providers/models.d.ts +0 -37
  73. package/lib/providers/models.js +0 -28
  74. package/lib/providers/provider-registry.d.ts +0 -49
  75. package/lib/providers/provider-registry.js +0 -72
  76. package/lib/providers/provider-tools.d.ts +0 -36
  77. package/lib/providers/provider-tools.js +0 -93
  78. package/lib/skills/index.d.ts +0 -4
  79. package/lib/skills/index.js +0 -7
  80. package/lib/skills/parse-skill.d.ts +0 -25
  81. package/lib/skills/parse-skill.js +0 -69
  82. package/lib/skills/skill-loader.d.ts +0 -25
  83. package/lib/skills/skill-loader.js +0 -133
  84. package/lib/skills/skill-registry.d.ts +0 -31
  85. package/lib/skills/skill-registry.js +0 -100
  86. package/lib/skills/types.d.ts +0 -29
  87. package/lib/skills/types.js +0 -5
  88. package/lib/tools/commands.d.ts +0 -11
  89. package/lib/tools/commands.js +0 -154
  90. package/lib/tools/skills.d.ts +0 -9
  91. package/lib/tools/skills.js +0 -73
  92. package/lib/tools/tool-registry.d.ts +0 -35
  93. package/lib/tools/tool-registry.js +0 -55
  94. package/lib/tools/web.d.ts +0 -8
  95. package/lib/tools/web.js +0 -196
  96. package/src/agent.ts +0 -1441
  97. package/src/icons.ts +0 -11
  98. package/src/providers/built-in-providers.ts +0 -241
  99. package/src/providers/generated-context-windows.ts +0 -102
  100. package/src/providers/model-info.ts +0 -88
  101. package/src/providers/models.ts +0 -76
  102. package/src/providers/provider-registry.ts +0 -88
  103. package/src/providers/provider-tools.ts +0 -179
  104. package/src/skills/index.ts +0 -14
  105. package/src/skills/parse-skill.ts +0 -91
  106. package/src/skills/skill-loader.ts +0 -175
  107. package/src/skills/skill-registry.ts +0 -137
  108. package/src/skills/types.ts +0 -37
  109. package/src/tools/commands.ts +0 -210
  110. package/src/tools/skills.ts +0 -84
  111. package/src/tools/tool-registry.ts +0 -63
  112. package/src/tools/web.ts +0 -238
  113. package/src/types.d.ts +0 -4
  114. package/style/icons/jupyternaut-lite.svg +0 -7
@@ -1,3 +1,8 @@
1
+ import {
2
+ createCompletionModel,
3
+ IProviderRegistry,
4
+ SECRETS_NAMESPACE
5
+ } from '@jupyternaut/agent';
1
6
  import {
2
7
  CompletionHandler,
3
8
  IInlineCompletionContext,
@@ -8,12 +13,7 @@ import { NotebookPanel } from '@jupyterlab/notebook';
8
13
  import { generateText, type LanguageModel } from 'ai';
9
14
  import { ISecretsManager } from 'jupyter-secrets-manager';
10
15
 
11
- import { createCompletionModel } from '../providers/models';
12
- import {
13
- type IAISettingsModel,
14
- SECRETS_NAMESPACE,
15
- type IProviderRegistry
16
- } from '../tokens';
16
+ import type { IAISettingsModel } from '../tokens';
17
17
 
18
18
  /**
19
19
  * Configuration interface for provider-specific completion behavior
@@ -4,8 +4,6 @@ import type { TranslationBundle } from '@jupyterlab/translation';
4
4
 
5
5
  import ClearIcon from '@mui/icons-material/Clear';
6
6
 
7
- import React from 'react';
8
-
9
7
  import { AIChatModel } from '../chat-model';
10
8
 
11
9
  /**
@@ -1,7 +1,7 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import { useEffect, useState } from 'react';
2
2
  import { ReactWidget } from '@jupyterlab/ui-components';
3
3
  import type { TranslationBundle } from '@jupyterlab/translation';
4
- import { jupyternautIcon } from '../icons';
4
+ import { jupyternautIcon } from '@jupyternaut/agent';
5
5
  import type { IAISettingsModel } from '../tokens';
6
6
 
7
7
  const COMPLETION_STATUS_CLASS = 'jp-ai-completion-status';
@@ -2,7 +2,7 @@ import { InputToolbarRegistry, TooltippedButton } from '@jupyter/chat';
2
2
  import type { TranslationBundle } from '@jupyterlab/translation';
3
3
  import CheckIcon from '@mui/icons-material/Check';
4
4
  import { Menu, MenuItem, Typography } from '@mui/material';
5
- import React, { useCallback, useEffect, useState } from 'react';
5
+ import { useCallback, useEffect, useState } from 'react';
6
6
  import { AIChatModel } from '../chat-model';
7
7
  import type { IAISettingsModel } from '../tokens';
8
8
 
@@ -7,7 +7,7 @@ import {
7
7
  import type { TranslationBundle } from '@jupyterlab/translation';
8
8
  import React, { useEffect, useState } from 'react';
9
9
 
10
- import { AIChatModel } from '../chat-model';
10
+ import { IAIChatModel } from '../tokens';
11
11
 
12
12
  const COMPONENT_CLASS = 'jp-ai-SaveButton';
13
13
  const AUTOSAVE_BUTTON_CLASS = 'jp-ai-AutoSaveButton';
@@ -19,7 +19,7 @@ export interface ISaveButtonProps {
19
19
  /**
20
20
  * The chat model, used to listen for message changes for auto-save.
21
21
  */
22
- model: AIChatModel;
22
+ model: IAIChatModel;
23
23
  /**
24
24
  * The application language translator.
25
25
  */
@@ -40,7 +40,7 @@ export function SaveComponent(props: ISaveButtonProps): JSX.Element {
40
40
  * Effect that update the autosave state when it is updated on the model.
41
41
  */
42
42
  useEffect(() => {
43
- const updateAutosave = (_: AIChatModel, value: boolean) => {
43
+ const updateAutosave = (_: IAIChatModel, value: boolean) => {
44
44
  setAutosave(value);
45
45
  };
46
46
 
@@ -4,8 +4,6 @@ import type { TranslationBundle } from '@jupyterlab/translation';
4
4
 
5
5
  import StopIcon from '@mui/icons-material/Stop';
6
6
 
7
- import React from 'react';
8
-
9
7
  import { AIChatModel } from '../chat-model';
10
8
 
11
9
  /**
@@ -1,3 +1,11 @@
1
+ import { createProviderTools } from '@jupyternaut/agent';
2
+
3
+ import type {
4
+ INamedTool,
5
+ IProviderRegistry,
6
+ IToolRegistry
7
+ } from '@jupyternaut/agent';
8
+
1
9
  import { InputToolbarRegistry, TooltippedButton } from '@jupyter/chat';
2
10
 
3
11
  import type { TranslationBundle } from '@jupyterlab/translation';
@@ -8,18 +16,11 @@ import CheckIcon from '@mui/icons-material/Check';
8
16
 
9
17
  import { Divider, Menu, MenuItem, Tooltip, Typography } from '@mui/material';
10
18
 
11
- import React, { useCallback, useEffect, useState } from 'react';
19
+ import { useCallback, useEffect, useState } from 'react';
12
20
 
13
21
  import { AIChatModel } from '../chat-model';
14
22
 
15
- import { createProviderTools } from '../providers/provider-tools';
16
-
17
- import type {
18
- IAISettingsModel,
19
- INamedTool,
20
- IProviderRegistry,
21
- IToolRegistry
22
- } from '../tokens';
23
+ import type { IAISettingsModel } from '../tokens';
23
24
 
24
25
  const SELECT_ITEM_CLASS = 'jp-AIToolSelect-item';
25
26
 
@@ -1,8 +1,10 @@
1
+ import type { ITokenUsage } from '@jupyternaut/agent';
1
2
  import { ReactWidget, UseSignal } from '@jupyterlab/ui-components';
2
3
  import type { TranslationBundle } from '@jupyterlab/translation';
3
- import React from 'react';
4
4
  import { ISignal } from '@lumino/signaling';
5
- import type { IAISettingsModel, ITokenUsage } from '../tokens';
5
+ import React from 'react';
6
+
7
+ import type { IAISettingsModel } from '../tokens';
6
8
 
7
9
  /**
8
10
  * Props for the UsageDisplay component.
@@ -1,10 +1,11 @@
1
- import { CommandRegistry } from '@lumino/commands';
2
1
  import type {
3
- IAISettingsModel,
4
2
  IDiffManager,
5
3
  IShowCellDiffParams,
6
4
  IShowFileDiffParams
7
- } from './tokens';
5
+ } from '@jupyternaut/agent';
6
+ import { CommandRegistry } from '@lumino/commands';
7
+
8
+ import type { IAISettingsModel } from './tokens';
8
9
 
9
10
  /**
10
11
  * Command IDs for unified cell diffs
package/src/index.ts CHANGED
@@ -1,3 +1,29 @@
1
+ import {
2
+ anthropicProvider,
3
+ createBrowserFetchTool,
4
+ createDiscoverCommandsTool,
5
+ createDiscoverSkillsTool,
6
+ createExecuteCommandTool,
7
+ createLoadSkillTool,
8
+ genericProvider,
9
+ googleProvider,
10
+ loadSkillsFromPaths,
11
+ mistralProvider,
12
+ openaiProvider,
13
+ AgentManagerFactory,
14
+ IAgentManagerFactory,
15
+ IDiffManager,
16
+ IProviderRegistry,
17
+ IToolRegistry,
18
+ ISkillRegistry,
19
+ ProviderRegistry,
20
+ SECRETS_NAMESPACE,
21
+ SkillRegistry,
22
+ ToolRegistry
23
+ } from '@jupyternaut/agent';
24
+
25
+ import type { IAISecretsAccess, IProviderConfig } from '@jupyternaut/agent';
26
+
1
27
  import {
2
28
  ILabShell,
3
29
  ILayoutRestorer,
@@ -58,7 +84,7 @@ import {
58
84
  ToolbarButton
59
85
  } from '@jupyterlab/ui-components';
60
86
 
61
- import { PromiseDelegate, UUID } from '@lumino/coreutils';
87
+ import { UUID } from '@lumino/coreutils';
62
88
 
63
89
  import { DisposableSet } from '@lumino/disposable';
64
90
 
@@ -68,44 +94,23 @@ import { IComponentsRendererFactory } from 'jupyter-chat-components';
68
94
 
69
95
  import { ISecretsManager, SecretsManager } from 'jupyter-secrets-manager';
70
96
 
71
- import { AgentManagerFactory } from './agent';
72
-
73
- import { AIChatModel } from './chat-model';
74
-
75
97
  import { RenderedMessageOutputAreaCompat } from './rendered-message-outputarea';
76
98
 
77
99
  import { ClearCommandProvider } from './chat-commands/clear';
78
100
 
79
101
  import { SkillsCommandProvider } from './chat-commands/skills';
80
102
 
81
- import { ProviderRegistry } from './providers/provider-registry';
82
-
83
103
  import { SaveComponentWidget } from './components/save-button';
84
104
 
85
105
  import { ChatModelHandler } from './chat-model-handler';
86
106
 
87
107
  import {
88
108
  CommandIds,
89
- IAgentManagerFactory,
90
- type IAISecretsAccess,
91
109
  IAISettingsModel,
92
110
  IChatModelHandler,
93
- IDiffManager,
94
- type IProviderConfig,
95
- IProviderRegistry,
96
- IToolRegistry,
97
- ISkillRegistry,
98
- SECRETS_NAMESPACE
111
+ IAIChatModel
99
112
  } from './tokens';
100
113
 
101
- import {
102
- anthropicProvider,
103
- googleProvider,
104
- mistralProvider,
105
- openaiProvider,
106
- genericProvider
107
- } from './providers/built-in-providers';
108
-
109
114
  import { AICompletionProvider } from './completion';
110
115
 
111
116
  import {
@@ -119,21 +124,8 @@ import {
119
124
 
120
125
  import { AISettingsModel } from './models/settings-model';
121
126
 
122
- import { loadSkillsFromPaths, SkillRegistry } from './skills';
123
-
124
127
  import { DiffManager } from './diff-manager';
125
128
 
126
- import { ToolRegistry } from './tools/tool-registry';
127
-
128
- import {
129
- createDiscoverCommandsTool,
130
- createExecuteCommandTool
131
- } from './tools/commands';
132
-
133
- import { createDiscoverSkillsTool, createLoadSkillTool } from './tools/skills';
134
-
135
- import { createBrowserFetchTool } from './tools/web';
136
-
137
129
  import { AISettingsWidget } from './widgets/ai-settings';
138
130
 
139
131
  import { MainAreaChat } from './widgets/main-area-chat';
@@ -526,7 +518,7 @@ const plugin: JupyterFrontEndPlugin<IChatTracker> = {
526
518
 
527
519
  let usageWidget: UsageWidget | null = null;
528
520
  chatPanel.chatOpened.connect((_, widget) => {
529
- const model = widget.model as AIChatModel;
521
+ const model = widget.model as IAIChatModel;
530
522
 
531
523
  // Add the widget to the tracker.
532
524
  tracker.add(widget);
@@ -585,11 +577,9 @@ const plugin: JupyterFrontEndPlugin<IChatTracker> = {
585
577
  );
586
578
 
587
579
  if (aiWriting) {
588
- widget.inputToolbarRegistry?.hide('send');
589
580
  widget.inputToolbarRegistry?.show('stop');
590
581
  } else {
591
582
  widget.inputToolbarRegistry?.hide('stop');
592
- widget.inputToolbarRegistry?.show('send');
593
583
  }
594
584
  }
595
585
 
@@ -628,7 +618,7 @@ const plugin: JupyterFrontEndPlugin<IChatTracker> = {
628
618
  args: widget => ({
629
619
  name: widget.model.name,
630
620
  area: widget instanceof MainAreaChat ? 'main' : 'side',
631
- provider: (widget.model as AIChatModel).agentManager.activeProvider
621
+ provider: (widget.model as IAIChatModel).agentManager.activeProvider
632
622
  }),
633
623
  name: widget => {
634
624
  const area = widget instanceof MainAreaChat ? 'main' : 'side';
@@ -662,24 +652,65 @@ const plugin: JupyterFrontEndPlugin<IChatTracker> = {
662
652
  );
663
653
 
664
654
  /**
665
- * The callback to approve or reject a tool.
655
+ * The callback for grouped tool calls permission decisions.
666
656
  */
667
- function toolCallApproval(
668
- targetId: string,
669
- approvalId: string,
670
- isApproved: boolean
657
+ function toolCallPermissionDecision(
658
+ sessionId: string,
659
+ toolCallId: string,
660
+ optionId: string
671
661
  ) {
672
- const model = tracker.find(chat => chat.model.name === targetId)?.model;
662
+ const model = tracker.find(chat => chat.model.name === sessionId)
663
+ ?.model as IAIChatModel;
673
664
  if (!model) {
674
665
  return;
675
666
  }
667
+
668
+ const isApproved = optionId === 'approve';
676
669
  isApproved
677
- ? (model as AIChatModel).agentManager.approveToolCall(approvalId)
678
- : (model as AIChatModel).agentManager.rejectToolCall(approvalId);
670
+ ? model.agentManager.approveToolCall(toolCallId)
671
+ : model.agentManager.rejectToolCall(toolCallId);
679
672
  }
680
673
 
681
674
  if (chatComponentsFactory) {
682
- chatComponentsFactory.toolCallApproval = toolCallApproval;
675
+ chatComponentsFactory.groupedToolCallCallbacks = {
676
+ ...chatComponentsFactory.groupedToolCallCallbacks,
677
+ toolCallPermissionDecision
678
+ };
679
+
680
+ chatComponentsFactory.queueMessageCallbacks = {
681
+ ...chatComponentsFactory.queueMessageCallbacks,
682
+ removeQueuedMessage: (targetId: string, messageId: string) => {
683
+ const model = tracker.find(
684
+ chat => chat.model.name === targetId
685
+ )?.model;
686
+ if (!model) {
687
+ return;
688
+ }
689
+ (model as IAIChatModel).removeQueuedMessage(messageId);
690
+ },
691
+ reorderQueuedMessages: (targetId: string, messageIds: string[]) => {
692
+ const model = tracker.find(
693
+ chat => chat.model.name === targetId
694
+ )?.model;
695
+ if (!model) {
696
+ return;
697
+ }
698
+ (model as IAIChatModel).reorderQueuedMessages(messageIds);
699
+ },
700
+ editQueuedMessage: (
701
+ targetId: string,
702
+ messageId: string,
703
+ newBody: string
704
+ ) => {
705
+ const model = tracker.find(
706
+ chat => chat.model.name === targetId
707
+ )?.model;
708
+ if (!model) {
709
+ return;
710
+ }
711
+ (model as IAIChatModel).editQueuedMessage(messageId, newBody);
712
+ }
713
+ };
683
714
  }
684
715
 
685
716
  return tracker;
@@ -755,12 +786,13 @@ function registerCommands(
755
786
  }
756
787
  });
757
788
 
758
- const openInMain = (model: AIChatModel): MainAreaChat => {
789
+ const openInMain = (model: IAIChatModel): MainAreaChat => {
790
+ const inputToolbarRegistry = inputToolbarFactory.create();
759
791
  const content = new ChatWidget({
760
792
  model,
761
793
  rmRegistry,
762
794
  themeManager: themeManager ?? null,
763
- inputToolbarRegistry: inputToolbarFactory.create(),
795
+ inputToolbarRegistry,
764
796
  attachmentOpenerRegistry,
765
797
  chatCommandRegistry
766
798
  });
@@ -827,7 +859,7 @@ function registerCommands(
827
859
  return;
828
860
  }
829
861
  return tracker.find(widget => {
830
- const model = widget.model as AIChatModel;
862
+ const model = widget.model as IAIChatModel;
831
863
  return (
832
864
  (!name || widget.model.name === name) &&
833
865
  (!provider || model.agentManager.activeProvider === provider)
@@ -1064,11 +1096,11 @@ function registerCommands(
1064
1096
  return false;
1065
1097
  }
1066
1098
  let previousWidget: ChatWidget | MainAreaChat | undefined;
1067
- let previousModel: AIChatModel | undefined;
1099
+ let previousModel: IAIChatModel | undefined;
1068
1100
  tracker.forEach(widget => {
1069
1101
  if (widget.model.name === args.name) {
1070
1102
  previousWidget = widget;
1071
- previousModel = widget.model as AIChatModel;
1103
+ previousModel = widget.model as IAIChatModel;
1072
1104
  }
1073
1105
  });
1074
1106
 
@@ -1079,61 +1111,26 @@ function registerCommands(
1079
1111
  return false;
1080
1112
  }
1081
1113
 
1082
- // Listen for the widget updated in tracker, to ensure the previous model name
1083
- // has been updated. This is required to remove the widget from the restorer
1084
- // when the previous widget is disposed.
1085
- const trackerUpdated = new PromiseDelegate<boolean>();
1086
- const widgetUpdated = (_: any, widget: ChatWidget | MainAreaChat) => {
1087
- if (widget.model === previousModel) {
1088
- trackerUpdated.resolve(true);
1089
- }
1090
- };
1091
- tracker.widgetUpdated.connect(widgetUpdated);
1092
-
1093
- // Rename temporary the previous model to be able to reuse this name for the new
1094
- // model. The previous is intended to be disposed anyway.
1095
- previousModel.name = UUID.uuid4();
1096
-
1097
- // Create a new model by duplicating the previous model attributes.
1098
- const model = modelRegistry.createModel({
1099
- name: args.name as string,
1100
- activeProvider: previousModel.agentManager.activeProvider,
1101
- tokenUsage: previousModel.agentManager.tokenUsage,
1102
- messages: previousModel.messages,
1103
- autosave: previousModel.autosave,
1104
- title: previousModel.title
1105
- });
1106
-
1107
- // Wait (with timeout) for the tracker to have updated the previous widget.
1108
- const status = await Promise.any([
1109
- trackerUpdated.promise,
1110
- new Promise<boolean>(r =>
1111
- setTimeout(() => {
1112
- r(false);
1113
- }, 2000)
1114
- )
1115
- ]);
1116
- tracker.widgetUpdated.disconnect(widgetUpdated);
1117
-
1118
- if (!status) {
1119
- return false;
1120
- }
1121
-
1122
1114
  if (area === 'main') {
1123
- openInMain(model);
1115
+ // Temporarily bypass model disposal to transport model to main view
1116
+ // to keep the conversation when switching views
1117
+ // TODO: Remove this code when jupyter-chat PR #423 is merged and released
1118
+ const originalDispose = previousModel.dispose.bind(previousModel);
1119
+ previousModel.dispose = () => {};
1124
1120
 
1125
1121
  if (previousWidget instanceof ChatWidget) {
1126
- // Clean up the side-panel model entry before disposing the previous
1127
- // widget/model state.
1128
1122
  if (!disposeSideChatModel(previousModel)) {
1129
1123
  previousWidget.dispose();
1130
- previousModel.dispose();
1131
1124
  }
1132
1125
  }
1126
+
1127
+ // Restore model disposal and transport to main view
1128
+ previousModel.dispose = originalDispose;
1129
+ openInMain(previousModel);
1133
1130
  } else {
1131
+ // MainAreaChat disposal does not dispose the model internally, so this is safe.
1134
1132
  previousWidget?.dispose();
1135
- previousModel.dispose();
1136
- chatPanel.open({ model });
1133
+ chatPanel.open({ model: previousModel });
1137
1134
  }
1138
1135
 
1139
1136
  return true;
@@ -1162,15 +1159,15 @@ function registerCommands(
1162
1159
  caption: trans.__('Save the chat as local file'),
1163
1160
  icon: saveIcon,
1164
1161
  execute: async (args): Promise<boolean> => {
1165
- let model: AIChatModel | null = null;
1162
+ let model: IAIChatModel | null = null;
1166
1163
  if (args.name) {
1167
1164
  tracker.forEach(widget => {
1168
1165
  if (widget.model.name === args.name) {
1169
- model = widget.model as AIChatModel;
1166
+ model = widget.model as IAIChatModel;
1170
1167
  }
1171
1168
  });
1172
1169
  } else {
1173
- model = (tracker.currentWidget?.model as AIChatModel) ?? null;
1170
+ model = (tracker.currentWidget?.model as IAIChatModel) ?? null;
1174
1171
  }
1175
1172
  if (model === null) {
1176
1173
  console.log('No chat to save');
@@ -1207,15 +1204,15 @@ function registerCommands(
1207
1204
  console.warn('The restoration is not possible');
1208
1205
  return false;
1209
1206
  }
1210
- let model: AIChatModel | null = null;
1207
+ let model: IAIChatModel | null = null;
1211
1208
  if (args.name) {
1212
1209
  tracker.forEach(widget => {
1213
1210
  if (widget.model.name === args.name) {
1214
- model = widget.model as AIChatModel;
1211
+ model = widget.model as IAIChatModel;
1215
1212
  }
1216
1213
  });
1217
1214
  } else {
1218
- model = (tracker.currentWidget?.model as AIChatModel) ?? null;
1215
+ model = (tracker.currentWidget?.model as IAIChatModel) ?? null;
1219
1216
  }
1220
1217
  if (model === null) {
1221
1218
  console.warn('There is no chat to restore');
@@ -1751,4 +1748,3 @@ export default [
1751
1748
 
1752
1749
  // Export extension points for other extensions to use
1753
1750
  export * from './tokens';
1754
- export * from './icons';
@@ -1,12 +1,12 @@
1
- import { VDomModel } from '@jupyterlab/ui-components';
2
- import { ISettingRegistry } from '@jupyterlab/settingregistry';
3
-
4
- import {
1
+ import type {
5
2
  IAIConfig,
6
- IAISettingsModel,
7
3
  IMCPServerConfig,
8
4
  IProviderConfig
9
- } from '../tokens';
5
+ } from '@jupyternaut/agent';
6
+ import { VDomModel } from '@jupyterlab/ui-components';
7
+ import { ISettingRegistry } from '@jupyterlab/settingregistry';
8
+
9
+ import type { IAISettingsModel } from '../tokens';
10
10
 
11
11
  const PLUGIN_ID = '@jupyterlite/ai:settings-model';
12
12
 
@@ -29,6 +29,7 @@ export class AISettingsModel extends VDomModel implements IAISettingsModel {
29
29
  diffDisplayMode: 'split',
30
30
  skillsPaths: ['.agents/skills', '_agents/skills'],
31
31
  chatBackupDirectory: '',
32
+ autoTitle: false,
32
33
  commandsRequiringApproval: [
33
34
  'notebook:restart-run-all',
34
35
  'notebook:run-cell',