@jupyterlite/ai 0.15.0 → 0.17.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 (45) hide show
  1. package/lib/agent.d.ts +12 -2
  2. package/lib/agent.js +112 -17
  3. package/lib/chat-commands/clear.js +1 -1
  4. package/lib/chat-model-handler.js +4 -1
  5. package/lib/chat-model.d.ts +25 -24
  6. package/lib/chat-model.js +262 -132
  7. package/lib/components/clear-button.d.ts +1 -1
  8. package/lib/components/clear-button.js +1 -1
  9. package/lib/components/index.d.ts +1 -1
  10. package/lib/components/index.js +1 -1
  11. package/lib/components/{token-usage-display.d.ts → usage-display.d.ts} +11 -11
  12. package/lib/components/usage-display.js +109 -0
  13. package/lib/index.js +205 -20
  14. package/lib/models/settings-model.js +1 -0
  15. package/lib/providers/built-in-providers.js +5 -0
  16. package/lib/providers/generated-context-windows.d.ts +8 -0
  17. package/lib/providers/generated-context-windows.js +96 -0
  18. package/lib/providers/model-info.d.ts +3 -0
  19. package/lib/providers/model-info.js +58 -0
  20. package/lib/tokens.d.ts +34 -3
  21. package/lib/tokens.js +8 -7
  22. package/lib/widgets/ai-settings.js +9 -0
  23. package/lib/widgets/main-area-chat.d.ts +1 -0
  24. package/lib/widgets/main-area-chat.js +10 -4
  25. package/lib/widgets/provider-config-dialog.js +18 -5
  26. package/package.json +3 -2
  27. package/schema/settings-model.json +11 -0
  28. package/src/agent.ts +151 -21
  29. package/src/chat-commands/clear.ts +1 -1
  30. package/src/chat-model-handler.ts +6 -1
  31. package/src/chat-model.ts +350 -175
  32. package/src/components/clear-button.tsx +3 -3
  33. package/src/components/index.ts +1 -1
  34. package/src/components/usage-display.tsx +208 -0
  35. package/src/index.ts +250 -26
  36. package/src/models/settings-model.ts +1 -0
  37. package/src/providers/built-in-providers.ts +5 -0
  38. package/src/providers/generated-context-windows.ts +102 -0
  39. package/src/providers/model-info.ts +88 -0
  40. package/src/tokens.ts +46 -10
  41. package/src/widgets/ai-settings.tsx +42 -0
  42. package/src/widgets/main-area-chat.ts +12 -4
  43. package/src/widgets/provider-config-dialog.tsx +45 -5
  44. package/lib/components/token-usage-display.js +0 -72
  45. package/src/components/token-usage-display.tsx +0 -137
package/lib/chat-model.js CHANGED
@@ -49,6 +49,31 @@ export class AIChatModel extends AbstractChatModel {
49
49
  }
50
50
  this.setReady();
51
51
  }
52
+ /**
53
+ * A signal emitting when the chat name has changed.
54
+ */
55
+ get nameChanged() {
56
+ return this._nameChanged;
57
+ }
58
+ /**
59
+ * The title of the chat.
60
+ */
61
+ get title() {
62
+ return this._title;
63
+ }
64
+ set title(value) {
65
+ this._title = value;
66
+ if (this.autosave) {
67
+ this._autosaveDebouncer.invoke();
68
+ }
69
+ this._titleChanged.emit(this._title);
70
+ }
71
+ /**
72
+ * A signal emitting when the chat title has changed.
73
+ */
74
+ get titleChanged() {
75
+ return this._titleChanged;
76
+ }
52
77
  /**
53
78
  * Whether to save the chat automatically.
54
79
  */
@@ -74,12 +99,6 @@ export class AIChatModel extends AbstractChatModel {
74
99
  get autosaveChanged() {
75
100
  return this._autosaveChanged;
76
101
  }
77
- /**
78
- * A signal emitting when the chat name has changed.
79
- */
80
- get nameChanged() {
81
- return this._nameChanged;
82
- }
83
102
  /**
84
103
  * Gets the current user information.
85
104
  */
@@ -135,10 +154,10 @@ export class AIChatModel extends AbstractChatModel {
135
154
  /**
136
155
  * Clears all messages from the chat and resets conversation state.
137
156
  */
138
- clearMessages = () => {
157
+ clearMessages = async () => {
139
158
  this.messagesDeleted(0, this.messages.length);
140
159
  this._toolContexts.clear();
141
- this._agentManager.clearHistory();
160
+ await this._agentManager.clearHistory();
142
161
  };
143
162
  /**
144
163
  * Adds a non-user message to the chat (used by chat commands).
@@ -192,11 +211,18 @@ export class AIChatModel extends AbstractChatModel {
192
211
  // Process attachments and add their content to the message
193
212
  let enhancedMessage = message.body;
194
213
  if (this.input.attachments.length > 0) {
195
- const attachmentContents = await this._processAttachments(this.input.attachments);
214
+ const { textContents, binaryParts } = await Private.processAttachments(this.input.attachments, this.input.documentManager);
196
215
  this.input.clearAttachments();
197
- if (attachmentContents.length > 0) {
198
- enhancedMessage +=
199
- '\n\n--- Attached Files ---\n' + attachmentContents.join('\n\n');
216
+ let textPart = message.body;
217
+ if (textContents.length > 0) {
218
+ textPart +=
219
+ '\n\n--- Attached Files ---\n' + textContents.join('\n\n');
220
+ }
221
+ if (binaryParts.length > 0) {
222
+ enhancedMessage = [{ type: 'text', text: textPart }, ...binaryParts];
223
+ }
224
+ else {
225
+ enhancedMessage = textPart;
200
226
  }
201
227
  }
202
228
  this.updateWriters([{ user: this._getAIUser() }]);
@@ -258,7 +284,7 @@ export class AIChatModel extends AbstractChatModel {
258
284
  return false;
259
285
  }
260
286
  const contentModel = await this._contentsManager
261
- .get(filepath, { content: true })
287
+ .get(filepath, { content: true, type: 'file', format: 'text' })
262
288
  .catch(() => {
263
289
  if (!silent) {
264
290
  console.log(`There is no backup for chat '${this.name}'`);
@@ -268,7 +294,13 @@ export class AIChatModel extends AbstractChatModel {
268
294
  if (!contentModel) {
269
295
  return false;
270
296
  }
271
- const content = JSON.parse(contentModel.content);
297
+ let content;
298
+ try {
299
+ content = JSON.parse(contentModel.content);
300
+ }
301
+ catch (e) {
302
+ throw `Error when parsing the chat ${filepath}\n${e}`;
303
+ }
272
304
  if (content.metadata?.provider) {
273
305
  if (this._settingsModel.getProvider(content.metadata.provider)) {
274
306
  this._agentManager.activeProvider = content.metadata.provider;
@@ -293,12 +325,33 @@ export class AIChatModel extends AbstractChatModel {
293
325
  attachments
294
326
  };
295
327
  });
296
- this.clearMessages();
328
+ await this.clearMessages();
297
329
  this.messagesInserted(0, messages);
298
330
  this._agentManager.setHistory(messages);
299
331
  this.autosave = content.metadata?.autosave ?? false;
332
+ this.title = content.metadata?.title ?? null;
300
333
  return true;
301
334
  };
335
+ /**
336
+ * Request a title to this chat, regarding the message history.
337
+ */
338
+ async requestTitle() {
339
+ const history = this.messages
340
+ .filter(msg => msg.body !== '')
341
+ .map(msg => `${msg.sender.username === 'ai-assistant' ? 'assistant' : 'user'}: ${msg.body}`)
342
+ .join('\n');
343
+ const messages = [
344
+ {
345
+ role: 'system',
346
+ content: "Generate a concise title (no more than 10 words) for the following conversation. Do not use formatting. Focus on the user's main intent."
347
+ },
348
+ {
349
+ role: 'user',
350
+ content: history
351
+ }
352
+ ];
353
+ return this.agentManager.textResponse(messages);
354
+ }
302
355
  /**
303
356
  * Serialize the model for backup
304
357
  */
@@ -342,7 +395,8 @@ export class AIChatModel extends AbstractChatModel {
342
395
  attachments,
343
396
  metadata: {
344
397
  provider,
345
- autosave: this.autosave
398
+ autosave: this.autosave,
399
+ ...(this.title ? { title: this.title } : {})
346
400
  }
347
401
  };
348
402
  }
@@ -652,49 +706,216 @@ export class AIChatModel extends AbstractChatModel {
652
706
  }
653
707
  });
654
708
  }
709
+ // Private fields
710
+ _settingsModel;
711
+ _user;
712
+ _toolContexts = new Map();
713
+ _agentManager;
714
+ _currentStreamingMessage = null;
715
+ _nameChanged = new Signal(this);
716
+ _contentsManager;
717
+ _autosave = false;
718
+ _autosaveChanged = new Signal(this);
719
+ _autosaveDebouncer;
720
+ _title = null;
721
+ _titleChanged = new Signal(this);
722
+ }
723
+ var Private;
724
+ (function (Private) {
725
+ const isPlainObject = (value) => {
726
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
727
+ };
728
+ const isDisplayOutput = (value) => {
729
+ if (!isPlainObject(value)) {
730
+ return false;
731
+ }
732
+ const output = value;
733
+ return (nbformat.isDisplayData(output) ||
734
+ nbformat.isDisplayUpdate(output) ||
735
+ nbformat.isExecuteResult(output));
736
+ };
737
+ const toMimeBundle = (value, trustedMimeTypes) => {
738
+ const data = value.data;
739
+ if (!isPlainObject(data) || Object.keys(data).length === 0) {
740
+ return null;
741
+ }
742
+ return {
743
+ data: data,
744
+ ...(isPlainObject(value.metadata)
745
+ ? { metadata: value.metadata }
746
+ : {}),
747
+ // MIME auto-rendering only runs for explicitly configured command IDs.
748
+ // Trust handling is configurable to keep risky MIME execution opt-in.
749
+ ...(Object.keys(data).some(m => trustedMimeTypes.has(m))
750
+ ? { trusted: true }
751
+ : {})
752
+ };
753
+ };
754
+ /**
755
+ * Normalize arbitrary tool payloads into canonical display outputs.
756
+ *
757
+ * Tool outputs are not guaranteed to be raw Jupyter IOPub messages; they are
758
+ * often wrapped objects (for example `{ success, result: { outputs: [...] } }`).
759
+ */
760
+ const toDisplayOutputs = (value) => {
761
+ if (isDisplayOutput(value)) {
762
+ return [value];
763
+ }
764
+ if (Array.isArray(value)) {
765
+ return value.filter(isDisplayOutput);
766
+ }
767
+ if (!isPlainObject(value)) {
768
+ return [];
769
+ }
770
+ if (Array.isArray(value.outputs)) {
771
+ return value.outputs.filter(isDisplayOutput);
772
+ }
773
+ if ('result' in value) {
774
+ return toDisplayOutputs(value.result);
775
+ }
776
+ return [];
777
+ };
778
+ /**
779
+ * Extract rendermime-ready mime bundles from arbitrary tool results.
780
+ */
781
+ function extractMimeBundlesFromUnknown(content, options = {}) {
782
+ const bundles = [];
783
+ const outputs = toDisplayOutputs(content);
784
+ const trustedMimeTypes = new Set(options.trustedMimeTypes ?? []);
785
+ for (const output of outputs) {
786
+ const bundle = toMimeBundle(output, trustedMimeTypes);
787
+ if (bundle) {
788
+ bundles.push(bundle);
789
+ }
790
+ }
791
+ return bundles;
792
+ }
793
+ Private.extractMimeBundlesFromUnknown = extractMimeBundlesFromUnknown;
794
+ function formatToolOutput(outputData) {
795
+ if (typeof outputData === 'string') {
796
+ return outputData;
797
+ }
798
+ try {
799
+ return JSON.stringify(outputData, null, 2);
800
+ }
801
+ catch {
802
+ return '[Complex object - cannot serialize]';
803
+ }
804
+ }
805
+ Private.formatToolOutput = formatToolOutput;
655
806
  /**
656
- * Processes file attachments and returns their content as formatted strings.
807
+ * Processes file attachments and returns text contents and binary parts separately.
657
808
  * @param attachments Array of file attachments to process
658
- * @returns Array of formatted attachment contents
809
+ * @param documentManager Optional document manager for file operations
810
+ * @returns Text contents and binary parts
659
811
  */
660
- async _processAttachments(attachments) {
661
- const contents = [];
812
+ async function processAttachments(attachments, documentManager) {
813
+ const textContents = [];
814
+ const binaryParts = [];
815
+ if (!documentManager) {
816
+ return { textContents, binaryParts };
817
+ }
662
818
  for (const attachment of attachments) {
663
819
  try {
664
820
  if (attachment.type === 'notebook' && attachment.cells?.length) {
665
- const cellContents = await this._readNotebookCells(attachment);
821
+ const cellContents = await readNotebookCells(attachment, documentManager);
666
822
  if (cellContents) {
667
- contents.push(cellContents);
823
+ textContents.push(cellContents);
668
824
  }
669
825
  }
670
826
  else {
671
- const fileContent = await this._readFileAttachment(attachment);
672
- if (fileContent) {
673
- const fileExtension = PathExt.extname(attachment.value).toLowerCase();
674
- const language = fileExtension === '.ipynb' ? 'json' : '';
675
- contents.push(`**File: ${attachment.value}**\n\`\`\`${language}\n${fileContent}\n\`\`\``);
827
+ let mimetype = attachment.mimetype;
828
+ const fileExtension = PathExt.extname(attachment.value).toLowerCase();
829
+ // Fetch mimetype from server metadata if not provided
830
+ if (!mimetype) {
831
+ try {
832
+ const diskModel = await documentManager.services.contents.get(attachment.value, { content: false });
833
+ mimetype = diskModel?.mimetype;
834
+ }
835
+ catch (e) {
836
+ console.warn(`Failed to fetch metadata for ${attachment.value}:`, e);
837
+ }
838
+ }
839
+ if (mimetype?.startsWith('image/')) {
840
+ const data = await readBinaryAttachment(attachment, documentManager);
841
+ if (data) {
842
+ binaryParts.push({
843
+ type: 'image',
844
+ image: data,
845
+ mediaType: mimetype
846
+ });
847
+ }
848
+ }
849
+ else if (mimetype === 'application/pdf') {
850
+ const data = await readBinaryAttachment(attachment, documentManager);
851
+ if (data) {
852
+ binaryParts.push({
853
+ type: 'file',
854
+ data,
855
+ mediaType: mimetype,
856
+ filename: PathExt.basename(attachment.value)
857
+ });
858
+ }
859
+ }
860
+ else {
861
+ const fileContent = await readFileAttachment(attachment, documentManager);
862
+ if (fileContent) {
863
+ const language = fileExtension === '.ipynb' ||
864
+ mimetype === 'application/x-ipynb+json'
865
+ ? 'json'
866
+ : '';
867
+ textContents.push(`**File: ${attachment.value}**\n\`\`\`${language}\n${fileContent}\n\`\`\``);
868
+ }
676
869
  }
677
870
  }
678
871
  }
679
872
  catch (error) {
680
873
  console.warn(`Failed to read attachment ${attachment.value}:`, error);
681
- contents.push(`**File: ${attachment.value}** (Could not read file)`);
874
+ textContents.push(`**File: ${attachment.value}** (Could not read file)`);
682
875
  }
683
876
  }
684
- return contents;
877
+ return { textContents, binaryParts };
685
878
  }
879
+ Private.processAttachments = processAttachments;
880
+ /**
881
+ * Reads a binary attachment and returns its base64-encoded content.
882
+ * @param attachment The attachment to read
883
+ * @param documentManager Optional document manager for file operations
884
+ * @returns Base64 string or null if unable to read
885
+ */
886
+ async function readBinaryAttachment(attachment, documentManager) {
887
+ if (!documentManager) {
888
+ return null;
889
+ }
890
+ try {
891
+ const diskModel = await documentManager.services.contents.get(attachment.value, { content: true });
892
+ if (diskModel?.content && diskModel.format === 'base64') {
893
+ // Strip whitespace/newlines
894
+ return diskModel.content.replace(/\s/g, '');
895
+ }
896
+ return null;
897
+ }
898
+ catch (error) {
899
+ console.warn(`Failed to read binary attachment ${attachment.value}:`, error);
900
+ return null;
901
+ }
902
+ }
903
+ Private.readBinaryAttachment = readBinaryAttachment;
686
904
  /**
687
905
  * Reads the content of a notebook cell.
688
906
  * @param attachment The notebook attachment to read
907
+ * @param documentManager Optional document manager for file operations
689
908
  * @returns Cell content as string or null if unable to read
690
909
  */
691
- async _readNotebookCells(attachment) {
692
- if (attachment.type !== 'notebook' || !attachment.cells) {
910
+ async function readNotebookCells(attachment, documentManager) {
911
+ if (attachment.type !== 'notebook' ||
912
+ !attachment.cells ||
913
+ !documentManager) {
693
914
  return null;
694
915
  }
695
916
  try {
696
917
  // Try reading from live notebook if open
697
- const widget = this.input.documentManager?.findWidget(attachment.value);
918
+ const widget = documentManager.findWidget(attachment.value);
698
919
  let cellData;
699
920
  let kernelLang = 'text';
700
921
  const ymodel = widget?.context.model.sharedModel;
@@ -708,7 +929,7 @@ export class AIChatModel extends AbstractChatModel {
708
929
  }
709
930
  else {
710
931
  // Fallback: reading from disk
711
- const model = await this.input.documentManager?.services.contents.get(attachment.value);
932
+ const model = await documentManager.services.contents.get(attachment.value);
712
933
  if (!model || model.type !== 'notebook') {
713
934
  return null;
714
935
  }
@@ -823,19 +1044,22 @@ export class AIChatModel extends AbstractChatModel {
823
1044
  return null;
824
1045
  }
825
1046
  }
1047
+ Private.readNotebookCells = readNotebookCells;
826
1048
  /**
827
1049
  * Reads the content of a file attachment.
828
1050
  * @param attachment The file attachment to read
1051
+ * @param documentManager Optional document manager for file operations
829
1052
  * @returns File content as string or null if unable to read
830
1053
  */
831
- async _readFileAttachment(attachment) {
1054
+ async function readFileAttachment(attachment, documentManager) {
832
1055
  // Handle both 'file' and 'notebook' types since both have a 'value' path
833
- if (attachment.type !== 'file' && attachment.type !== 'notebook') {
1056
+ if ((attachment.type !== 'file' && attachment.type !== 'notebook') ||
1057
+ !documentManager) {
834
1058
  return null;
835
1059
  }
836
1060
  try {
837
1061
  // Try reading from an open widget first
838
- const widget = this.input.documentManager?.findWidget(attachment.value);
1062
+ const widget = documentManager.findWidget(attachment.value);
839
1063
  if (widget && widget.context && widget.context.model) {
840
1064
  const model = widget.context.model;
841
1065
  const ymodel = model.sharedModel;
@@ -847,7 +1071,7 @@ export class AIChatModel extends AbstractChatModel {
847
1071
  }
848
1072
  }
849
1073
  // If not open, load from disk
850
- const diskModel = await this.input.documentManager?.services.contents.get(attachment.value);
1074
+ const diskModel = await documentManager.services.contents.get(attachment.value);
851
1075
  if (!diskModel?.content) {
852
1076
  return null;
853
1077
  }
@@ -873,99 +1097,5 @@ export class AIChatModel extends AbstractChatModel {
873
1097
  return null;
874
1098
  }
875
1099
  }
876
- // Private fields
877
- _settingsModel;
878
- _user;
879
- _toolContexts = new Map();
880
- _agentManager;
881
- _currentStreamingMessage = null;
882
- _nameChanged = new Signal(this);
883
- _contentsManager;
884
- _autosave = false;
885
- _autosaveChanged = new Signal(this);
886
- _autosaveDebouncer;
887
- }
888
- var Private;
889
- (function (Private) {
890
- const isPlainObject = (value) => {
891
- return typeof value === 'object' && value !== null && !Array.isArray(value);
892
- };
893
- const isDisplayOutput = (value) => {
894
- if (!isPlainObject(value)) {
895
- return false;
896
- }
897
- const output = value;
898
- return (nbformat.isDisplayData(output) ||
899
- nbformat.isDisplayUpdate(output) ||
900
- nbformat.isExecuteResult(output));
901
- };
902
- const toMimeBundle = (value, trustedMimeTypes) => {
903
- const data = value.data;
904
- if (!isPlainObject(data) || Object.keys(data).length === 0) {
905
- return null;
906
- }
907
- return {
908
- data: data,
909
- ...(isPlainObject(value.metadata)
910
- ? { metadata: value.metadata }
911
- : {}),
912
- // MIME auto-rendering only runs for explicitly configured command IDs.
913
- // Trust handling is configurable to keep risky MIME execution opt-in.
914
- ...(Object.keys(data).some(m => trustedMimeTypes.has(m))
915
- ? { trusted: true }
916
- : {})
917
- };
918
- };
919
- /**
920
- * Normalize arbitrary tool payloads into canonical display outputs.
921
- *
922
- * Tool outputs are not guaranteed to be raw Jupyter IOPub messages; they are
923
- * often wrapped objects (for example `{ success, result: { outputs: [...] } }`).
924
- */
925
- const toDisplayOutputs = (value) => {
926
- if (isDisplayOutput(value)) {
927
- return [value];
928
- }
929
- if (Array.isArray(value)) {
930
- return value.filter(isDisplayOutput);
931
- }
932
- if (!isPlainObject(value)) {
933
- return [];
934
- }
935
- if (Array.isArray(value.outputs)) {
936
- return value.outputs.filter(isDisplayOutput);
937
- }
938
- if ('result' in value) {
939
- return toDisplayOutputs(value.result);
940
- }
941
- return [];
942
- };
943
- /**
944
- * Extract rendermime-ready mime bundles from arbitrary tool results.
945
- */
946
- function extractMimeBundlesFromUnknown(content, options = {}) {
947
- const bundles = [];
948
- const outputs = toDisplayOutputs(content);
949
- const trustedMimeTypes = new Set(options.trustedMimeTypes ?? []);
950
- for (const output of outputs) {
951
- const bundle = toMimeBundle(output, trustedMimeTypes);
952
- if (bundle) {
953
- bundles.push(bundle);
954
- }
955
- }
956
- return bundles;
957
- }
958
- Private.extractMimeBundlesFromUnknown = extractMimeBundlesFromUnknown;
959
- function formatToolOutput(outputData) {
960
- if (typeof outputData === 'string') {
961
- return outputData;
962
- }
963
- try {
964
- return JSON.stringify(outputData, null, 2);
965
- }
966
- catch {
967
- return '[Complex object - cannot serialize]';
968
- }
969
- }
970
- Private.formatToolOutput = formatToolOutput;
1100
+ Private.readFileAttachment = readFileAttachment;
971
1101
  })(Private || (Private = {}));
@@ -7,7 +7,7 @@ export interface IClearButtonProps extends InputToolbarRegistry.IToolbarItemProp
7
7
  /**
8
8
  * The function to clear messages.
9
9
  */
10
- clearMessages: () => void;
10
+ clearMessages: () => Promise<void>;
11
11
  /**
12
12
  * The application language translator.
13
13
  */
@@ -21,7 +21,7 @@ export function clearItem(translator) {
21
21
  return {
22
22
  element: (props) => {
23
23
  const { model } = props;
24
- const clearMessages = () => model.chatContext.clearMessages();
24
+ const clearMessages = async () => await model.chatContext.clearMessages();
25
25
  const clearProps = {
26
26
  ...props,
27
27
  clearMessages,
@@ -2,5 +2,5 @@ export * from './clear-button';
2
2
  export * from './completion-status';
3
3
  export * from './model-select';
4
4
  export * from './stop-button';
5
- export * from './token-usage-display';
5
+ export * from './usage-display';
6
6
  export * from './tool-select';
@@ -2,5 +2,5 @@ export * from './clear-button';
2
2
  export * from './completion-status';
3
3
  export * from './model-select';
4
4
  export * from './stop-button';
5
- export * from './token-usage-display';
5
+ export * from './usage-display';
6
6
  export * from './tool-select';
@@ -4,9 +4,9 @@ import React from 'react';
4
4
  import { ISignal } from '@lumino/signaling';
5
5
  import type { IAISettingsModel, ITokenUsage } from '../tokens';
6
6
  /**
7
- * Props for the TokenUsageDisplay component.
7
+ * Props for the UsageDisplay component.
8
8
  */
9
- export interface ITokenUsageDisplayProps {
9
+ export interface IUsageDisplayProps {
10
10
  /**
11
11
  * The token usage changed signal
12
12
  */
@@ -25,24 +25,24 @@ export interface ITokenUsageDisplayProps {
25
25
  translator: TranslationBundle;
26
26
  }
27
27
  /**
28
- * React component that displays token usage information.
29
- * Shows input/output token counts with up/down arrows.
30
- * Only renders when token usage display is enabled in settings.
28
+ * React component that displays usage information.
29
+ * Shows input/output token counts and optional estimated context usage.
30
+ * Only renders when token or context usage display is enabled in settings.
31
31
  */
32
- export declare const TokenUsageDisplay: React.FC<ITokenUsageDisplayProps>;
32
+ export declare const UsageDisplay: React.FC<IUsageDisplayProps>;
33
33
  /**
34
- * JupyterLab widget wrapper for the TokenUsageDisplay component.
34
+ * JupyterLab widget wrapper for the UsageDisplay component.
35
35
  * Extends ReactWidget to integrate with the JupyterLab widget system.
36
36
  */
37
- export declare class TokenUsageWidget extends ReactWidget {
37
+ export declare class UsageWidget extends ReactWidget {
38
38
  /**
39
- * Creates a new TokenUsageWidget instance.
39
+ * Creates a new UsageWidget instance.
40
40
  * @param options - Configuration options containing required models
41
41
  */
42
- constructor(options: ITokenUsageDisplayProps);
42
+ constructor(options: IUsageDisplayProps);
43
43
  /**
44
44
  * Renders the React component within the widget.
45
- * @returns The TokenUsageDisplay React element
45
+ * @returns The UsageDisplay React element
46
46
  */
47
47
  protected render(): React.ReactElement;
48
48
  private _options;