@jupyter/chat 0.1.0 → 0.3.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 (55) hide show
  1. package/lib/active-cell-manager.d.ts +151 -0
  2. package/lib/active-cell-manager.js +201 -0
  3. package/lib/components/chat-input.d.ts +14 -4
  4. package/lib/components/chat-input.js +118 -10
  5. package/lib/components/chat-messages.d.ts +45 -15
  6. package/lib/components/chat-messages.js +237 -55
  7. package/lib/components/chat.d.ts +21 -6
  8. package/lib/components/chat.js +15 -45
  9. package/lib/components/code-blocks/code-toolbar.d.ts +13 -0
  10. package/lib/components/code-blocks/code-toolbar.js +70 -0
  11. package/lib/components/{copy-button.d.ts → code-blocks/copy-button.d.ts} +1 -0
  12. package/lib/components/code-blocks/copy-button.js +43 -0
  13. package/lib/components/mui-extras/contrasting-tooltip.d.ts +6 -0
  14. package/lib/components/mui-extras/contrasting-tooltip.js +21 -0
  15. package/lib/components/mui-extras/tooltipped-icon-button.d.ts +35 -0
  16. package/lib/components/mui-extras/tooltipped-icon-button.js +36 -0
  17. package/lib/components/rendermime-markdown.d.ts +2 -0
  18. package/lib/components/rendermime-markdown.js +29 -15
  19. package/lib/components/scroll-container.js +1 -19
  20. package/lib/icons.d.ts +2 -0
  21. package/lib/icons.js +10 -0
  22. package/lib/index.d.ts +2 -0
  23. package/lib/index.js +2 -0
  24. package/lib/model.d.ts +98 -14
  25. package/lib/model.js +197 -6
  26. package/lib/registry.d.ts +78 -0
  27. package/lib/registry.js +83 -0
  28. package/lib/types.d.ts +60 -4
  29. package/lib/widgets/chat-sidebar.d.ts +3 -4
  30. package/lib/widgets/chat-sidebar.js +2 -2
  31. package/lib/widgets/chat-widget.d.ts +2 -8
  32. package/lib/widgets/chat-widget.js +6 -6
  33. package/package.json +204 -200
  34. package/src/active-cell-manager.ts +318 -0
  35. package/src/components/chat-input.tsx +196 -50
  36. package/src/components/chat-messages.tsx +357 -95
  37. package/src/components/chat.tsx +43 -69
  38. package/src/components/code-blocks/code-toolbar.tsx +143 -0
  39. package/src/components/code-blocks/copy-button.tsx +68 -0
  40. package/src/components/mui-extras/contrasting-tooltip.tsx +27 -0
  41. package/src/components/mui-extras/tooltipped-icon-button.tsx +84 -0
  42. package/src/components/rendermime-markdown.tsx +44 -20
  43. package/src/components/scroll-container.tsx +1 -25
  44. package/src/icons.ts +12 -0
  45. package/src/index.ts +2 -0
  46. package/src/model.ts +275 -21
  47. package/src/registry.ts +129 -0
  48. package/src/types.ts +62 -4
  49. package/src/widgets/chat-sidebar.tsx +3 -15
  50. package/src/widgets/chat-widget.tsx +8 -21
  51. package/style/chat.css +40 -0
  52. package/style/icons/read.svg +11 -0
  53. package/style/icons/replace-cell.svg +8 -0
  54. package/lib/components/copy-button.js +0 -35
  55. package/src/components/copy-button.tsx +0 -55
@@ -0,0 +1,43 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import React, { useState, useCallback, useRef } from 'react';
6
+ import { copyIcon } from '@jupyterlab/ui-components';
7
+ import { TooltippedIconButton } from '../mui-extras/tooltipped-icon-button';
8
+ var CopyStatus;
9
+ (function (CopyStatus) {
10
+ CopyStatus[CopyStatus["None"] = 0] = "None";
11
+ CopyStatus[CopyStatus["Copying"] = 1] = "Copying";
12
+ CopyStatus[CopyStatus["Copied"] = 2] = "Copied";
13
+ })(CopyStatus || (CopyStatus = {}));
14
+ const COPYBTN_TEXT_BY_STATUS = {
15
+ [CopyStatus.None]: 'Copy to clipboard',
16
+ [CopyStatus.Copying]: 'Copying…',
17
+ [CopyStatus.Copied]: 'Copied!'
18
+ };
19
+ export function CopyButton(props) {
20
+ const [copyStatus, setCopyStatus] = useState(CopyStatus.None);
21
+ const timeoutId = useRef(null);
22
+ const copy = useCallback(async () => {
23
+ // ignore if we are already copying
24
+ if (copyStatus === CopyStatus.Copying) {
25
+ return;
26
+ }
27
+ try {
28
+ await navigator.clipboard.writeText(props.value);
29
+ }
30
+ catch (err) {
31
+ console.error('Failed to copy text: ', err);
32
+ setCopyStatus(CopyStatus.None);
33
+ return;
34
+ }
35
+ setCopyStatus(CopyStatus.Copied);
36
+ if (timeoutId.current) {
37
+ clearTimeout(timeoutId.current);
38
+ }
39
+ timeoutId.current = window.setTimeout(() => setCopyStatus(CopyStatus.None), 1000);
40
+ }, [copyStatus, props.value]);
41
+ return (React.createElement(TooltippedIconButton, { className: props.className, tooltip: COPYBTN_TEXT_BY_STATUS[copyStatus], placement: "top", onClick: copy, "aria-label": "Copy to clipboard" },
42
+ React.createElement(copyIcon.react, { height: "16px", width: "16px" })));
43
+ }
@@ -0,0 +1,6 @@
1
+ import { TooltipProps } from '@mui/material';
2
+ /**
3
+ * A restyled MUI tooltip component that is dark by default to improve contrast
4
+ * against JupyterLab's default light theme. TODO: support dark themes.
5
+ */
6
+ export declare const ContrastingTooltip: import("@emotion/styled").StyledComponent<TooltipProps & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import React from 'react';
6
+ import { styled, Tooltip, tooltipClasses } from '@mui/material';
7
+ /**
8
+ * A restyled MUI tooltip component that is dark by default to improve contrast
9
+ * against JupyterLab's default light theme. TODO: support dark themes.
10
+ */
11
+ export const ContrastingTooltip = styled(({ className, ...props }) => (React.createElement(Tooltip, { ...props, arrow: true, classes: { popper: className } })))(({ theme }) => ({
12
+ [`& .${tooltipClasses.tooltip}`]: {
13
+ backgroundColor: theme.palette.common.black,
14
+ color: theme.palette.common.white,
15
+ boxShadow: theme.shadows[1],
16
+ fontSize: 11
17
+ },
18
+ [`& .${tooltipClasses.arrow}`]: {
19
+ color: theme.palette.common.black
20
+ }
21
+ }));
@@ -0,0 +1,35 @@
1
+ /// <reference types="react" />
2
+ import { IconButtonProps, TooltipProps } from '@mui/material';
3
+ export type TooltippedIconButtonProps = {
4
+ onClick: () => unknown;
5
+ tooltip: string;
6
+ children: JSX.Element;
7
+ className?: string;
8
+ disabled?: boolean;
9
+ placement?: TooltipProps['placement'];
10
+ /**
11
+ * The offset of the tooltip popup.
12
+ *
13
+ * The expected syntax is defined by the Popper library:
14
+ * https://popper.js.org/docs/v2/modifiers/offset/
15
+ */
16
+ offset?: [number, number];
17
+ 'aria-label'?: string;
18
+ /**
19
+ * Props passed directly to the MUI `IconButton` component.
20
+ */
21
+ iconButtonProps?: IconButtonProps;
22
+ };
23
+ /**
24
+ * A component that renders an MUI `IconButton` with a high-contrast tooltip
25
+ * provided by `ContrastingTooltip`. This component differs from the MUI
26
+ * defaults in the following ways:
27
+ *
28
+ * - Shows the tooltip on hover even if disabled.
29
+ * - Renders the tooltip above the button by default.
30
+ * - Renders the tooltip closer to the button by default.
31
+ * - Lowers the opacity of the IconButton when disabled.
32
+ * - Renders the IconButton with `line-height: 0` to avoid showing extra
33
+ * vertical space in SVG icons.
34
+ */
35
+ export declare function TooltippedIconButton(props: TooltippedIconButtonProps): JSX.Element;
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import React from 'react';
6
+ import { IconButton } from '@mui/material';
7
+ import { ContrastingTooltip } from './contrasting-tooltip';
8
+ /**
9
+ * A component that renders an MUI `IconButton` with a high-contrast tooltip
10
+ * provided by `ContrastingTooltip`. This component differs from the MUI
11
+ * defaults in the following ways:
12
+ *
13
+ * - Shows the tooltip on hover even if disabled.
14
+ * - Renders the tooltip above the button by default.
15
+ * - Renders the tooltip closer to the button by default.
16
+ * - Lowers the opacity of the IconButton when disabled.
17
+ * - Renders the IconButton with `line-height: 0` to avoid showing extra
18
+ * vertical space in SVG icons.
19
+ */
20
+ export function TooltippedIconButton(props) {
21
+ var _a;
22
+ return (React.createElement(ContrastingTooltip, { title: props.tooltip, placement: (_a = props.placement) !== null && _a !== void 0 ? _a : 'top', slotProps: {
23
+ popper: {
24
+ modifiers: [
25
+ {
26
+ name: 'offset',
27
+ options: {
28
+ offset: [0, -8]
29
+ }
30
+ }
31
+ ]
32
+ }
33
+ } },
34
+ React.createElement("span", { className: props.className },
35
+ React.createElement(IconButton, { ...props.iconButtonProps, onClick: props.onClick, disabled: props.disabled, sx: { lineHeight: 0, ...(props.disabled && { opacity: 0.5 }) }, "aria-label": props['aria-label'] }, props.children))));
36
+ }
@@ -1,9 +1,11 @@
1
1
  import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
2
2
  import React from 'react';
3
+ import { IChatModel } from '../model';
3
4
  type RendermimeMarkdownProps = {
4
5
  markdownStr: string;
5
6
  rmRegistry: IRenderMimeRegistry;
6
7
  appendContent?: boolean;
8
+ model: IChatModel;
7
9
  edit?: () => void;
8
10
  delete?: () => void;
9
11
  };
@@ -2,9 +2,9 @@
2
2
  * Copyright (c) Jupyter Development Team.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
- import React, { useState, useEffect, useRef } from 'react';
6
- import ReactDOM from 'react-dom';
7
- import { CopyButton } from './copy-button';
5
+ import React, { useState, useEffect } from 'react';
6
+ import { createPortal } from 'react-dom';
7
+ import { CodeToolbar } from './code-blocks/code-toolbar';
8
8
  import { MessageToolbar } from './toolbar';
9
9
  const MD_MIME_TYPE = 'text/markdown';
10
10
  const RENDERMIME_MD_CLASS = 'jp-chat-rendermime-markdown';
@@ -21,7 +21,8 @@ function escapeLatexDelimiters(text) {
21
21
  function RendermimeMarkdownBase(props) {
22
22
  const appendContent = props.appendContent || false;
23
23
  const [renderedContent, setRenderedContent] = useState(null);
24
- const containerRef = useRef(null);
24
+ // each element is a two-tuple with the structure [codeToolbarRoot, codeToolbarProps].
25
+ const [codeToolbarDefns, setCodeToolbarDefns] = useState([]);
25
26
  useEffect(() => {
26
27
  const renderContent = async () => {
27
28
  var _a;
@@ -32,23 +33,36 @@ function RendermimeMarkdownBase(props) {
32
33
  const renderer = props.rmRegistry.createRenderer(MD_MIME_TYPE);
33
34
  await renderer.renderModel(model);
34
35
  (_a = props.rmRegistry.latexTypesetter) === null || _a === void 0 ? void 0 : _a.typeset(renderer.node);
35
- // Attach CopyButton to each <pre> block
36
- if (containerRef.current && renderer.node) {
37
- const preBlocks = renderer.node.querySelectorAll('pre');
38
- preBlocks.forEach(preBlock => {
39
- var _a;
40
- const copyButtonContainer = document.createElement('div');
41
- (_a = preBlock.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(copyButtonContainer, preBlock.nextSibling);
42
- ReactDOM.render(React.createElement(CopyButton, { value: preBlock.textContent || '' }), copyButtonContainer);
43
- });
36
+ if (!renderer.node) {
37
+ throw new Error('Rendermime was unable to render Markdown content within a chat message. Please report this upstream to Jupyter chat on GitHub.');
44
38
  }
39
+ const newCodeToolbarDefns = [];
40
+ // Attach CodeToolbar root element to each <pre> block
41
+ const preBlocks = renderer.node.querySelectorAll('pre');
42
+ preBlocks.forEach(preBlock => {
43
+ var _a;
44
+ const codeToolbarRoot = document.createElement('div');
45
+ (_a = preBlock.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(codeToolbarRoot, preBlock.nextSibling);
46
+ newCodeToolbarDefns.push([
47
+ codeToolbarRoot,
48
+ { model: props.model, content: preBlock.textContent || '' }
49
+ ]);
50
+ });
51
+ setCodeToolbarDefns(newCodeToolbarDefns);
45
52
  setRenderedContent(renderer.node);
46
53
  };
47
54
  renderContent();
48
55
  }, [props.markdownStr, props.rmRegistry]);
49
- return (React.createElement("div", { ref: containerRef, className: RENDERMIME_MD_CLASS },
56
+ return (React.createElement("div", { className: RENDERMIME_MD_CLASS },
50
57
  renderedContent &&
51
58
  (appendContent ? (React.createElement("div", { ref: node => node && node.appendChild(renderedContent) })) : (React.createElement("div", { ref: node => node && node.replaceChildren(renderedContent) }))),
52
- React.createElement(MessageToolbar, { edit: props.edit, delete: props.delete })));
59
+ React.createElement(MessageToolbar, { edit: props.edit, delete: props.delete }),
60
+ // Render a `CodeToolbar` element underneath each code block.
61
+ // We use ReactDOM.createPortal() so each `CodeToolbar` element is able
62
+ // to use the context in the main React tree.
63
+ codeToolbarDefns.map(codeToolbarDefn => {
64
+ const [codeToolbarRoot, codeToolbarProps] = codeToolbarDefn;
65
+ return createPortal(React.createElement(CodeToolbar, { ...codeToolbarProps }), codeToolbarRoot);
66
+ })));
53
67
  }
54
68
  export const RendermimeMarkdown = React.memo(RendermimeMarkdownBase);
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Jupyter Development Team.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
- import React, { useEffect, useMemo } from 'react';
5
+ import React, { useMemo } from 'react';
6
6
  import { Box } from '@mui/material';
7
7
  /**
8
8
  * Component that handles intelligent scrolling.
@@ -21,24 +21,6 @@ import { Box } from '@mui/material';
21
21
  */
22
22
  export function ScrollContainer(props) {
23
23
  const id = useMemo(() => 'jupyter-chat-scroll-container-' + Date.now().toString(), []);
24
- /**
25
- * Effect: Scroll the container to the bottom as soon as it is visible.
26
- */
27
- useEffect(() => {
28
- const el = document.querySelector(`#${id}`);
29
- if (!el) {
30
- return;
31
- }
32
- const observer = new IntersectionObserver(entries => {
33
- entries.forEach(entry => {
34
- if (entry.isIntersecting) {
35
- el.scroll({ top: 999999999 });
36
- }
37
- });
38
- }, { threshold: 1.0 });
39
- observer.observe(el);
40
- return () => observer.disconnect();
41
- }, []);
42
24
  return (React.createElement(Box, { id: id, sx: {
43
25
  overflowY: 'scroll',
44
26
  '& *': {
package/lib/icons.d.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  import { LabIcon } from '@jupyterlab/ui-components';
2
2
  export declare const chatIcon: LabIcon;
3
+ export declare const readIcon: LabIcon;
4
+ export declare const replaceCellIcon: LabIcon;
package/lib/icons.js CHANGED
@@ -5,7 +5,17 @@
5
5
  // This file is based on iconimports.ts in @jupyterlab/ui-components, but is manually generated.
6
6
  import { LabIcon } from '@jupyterlab/ui-components';
7
7
  import chatSvgStr from '../style/icons/chat.svg';
8
+ import readSvgStr from '../style/icons/read.svg';
9
+ import replaceCellSvg from '../style/icons/replace-cell.svg';
8
10
  export const chatIcon = new LabIcon({
9
11
  name: 'jupyter-chat::chat',
10
12
  svgstr: chatSvgStr
11
13
  });
14
+ export const readIcon = new LabIcon({
15
+ name: 'jupyter-chat::read',
16
+ svgstr: readSvgStr
17
+ });
18
+ export const replaceCellIcon = new LabIcon({
19
+ name: 'jupyter-ai::replace-cell',
20
+ svgstr: replaceCellSvg
21
+ });
package/lib/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export * from './icons';
2
2
  export * from './model';
3
+ export * from './registry';
3
4
  export * from './types';
5
+ export * from './active-cell-manager';
4
6
  export * from './widgets/chat-error';
5
7
  export * from './widgets/chat-sidebar';
6
8
  export * from './widgets/chat-widget';
package/lib/index.js CHANGED
@@ -4,7 +4,9 @@
4
4
  */
5
5
  export * from './icons';
6
6
  export * from './model';
7
+ export * from './registry';
7
8
  export * from './types';
9
+ export * from './active-cell-manager';
8
10
  export * from './widgets/chat-error';
9
11
  export * from './widgets/chat-sidebar';
10
12
  export * from './widgets/chat-widget';
package/lib/model.d.ts CHANGED
@@ -1,18 +1,28 @@
1
+ import { CommandRegistry } from '@lumino/commands';
1
2
  import { IDisposable } from '@lumino/disposable';
2
3
  import { ISignal } from '@lumino/signaling';
3
4
  import { IChatHistory, INewMessage, IChatMessage, IConfig, IUser } from './types';
5
+ import { IActiveCellManager } from './active-cell-manager';
4
6
  /**
5
7
  * The chat model interface.
6
8
  */
7
9
  export interface IChatModel extends IDisposable {
8
10
  /**
9
- * The chat model ID.
11
+ * The chat model name.
10
12
  */
11
- id: string;
13
+ name: string;
12
14
  /**
13
15
  * The configuration for the chat panel.
14
16
  */
15
17
  config: IConfig;
18
+ /**
19
+ * The indexes list of the unread messages.
20
+ */
21
+ unreadMessages: number[];
22
+ /**
23
+ * The indexes list of the messages currently in the viewport.
24
+ */
25
+ messagesInViewport?: number[];
16
26
  /**
17
27
  * The user connected to the chat panel.
18
28
  */
@@ -22,9 +32,25 @@ export interface IChatModel extends IDisposable {
22
32
  */
23
33
  readonly messages: IChatMessage[];
24
34
  /**
25
- * The signal emitted when the messages list is updated.
35
+ * Get the active cell manager.
36
+ */
37
+ readonly activeCellManager: IActiveCellManager | null;
38
+ /**
39
+ * A signal emitting when the messages list is updated.
26
40
  */
27
41
  readonly messagesUpdated: ISignal<IChatModel, void>;
42
+ /**
43
+ * A signal emitting when the messages list is updated.
44
+ */
45
+ get configChanged(): ISignal<IChatModel, IConfig>;
46
+ /**
47
+ * A signal emitting when unread messages change.
48
+ */
49
+ readonly unreadChanged?: ISignal<IChatModel, number[]>;
50
+ /**
51
+ * A signal emitting when the viewport change.
52
+ */
53
+ readonly viewportChanged?: ISignal<IChatModel, number[]>;
28
54
  /**
29
55
  * Send a message, to be defined depending on the chosen technology.
30
56
  * Default to no-op.
@@ -93,20 +119,53 @@ export declare class ChatModel implements IChatModel {
93
119
  * The chat messages list.
94
120
  */
95
121
  get messages(): IChatMessage[];
122
+ get activeCellManager(): IActiveCellManager | null;
123
+ /**
124
+ * The chat model id.
125
+ */
126
+ get id(): string | undefined;
127
+ set id(value: string | undefined);
128
+ /**
129
+ * The chat model name.
130
+ */
131
+ get name(): string;
132
+ set name(value: string);
96
133
  /**
97
- * The chat model ID.
134
+ * Timestamp of the last read message in local storage.
98
135
  */
99
- get id(): string;
100
- set id(value: string);
136
+ get lastRead(): number;
137
+ set lastRead(value: number);
101
138
  /**
102
139
  * The chat settings.
103
140
  */
104
141
  get config(): IConfig;
105
142
  set config(value: Partial<IConfig>);
106
143
  /**
107
- * The signal emitted when the messages list is updated.
144
+ * The indexes list of the unread messages.
145
+ */
146
+ get unreadMessages(): number[];
147
+ set unreadMessages(unread: number[]);
148
+ /**
149
+ * The indexes list of the messages currently in the viewport.
150
+ */
151
+ get messagesInViewport(): number[];
152
+ set messagesInViewport(values: number[]);
153
+ /**
154
+ * A signal emitting when the messages list is updated.
108
155
  */
109
156
  get messagesUpdated(): ISignal<IChatModel, void>;
157
+ /**
158
+ * A signal emitting when the messages list is updated.
159
+ */
160
+ get configChanged(): ISignal<IChatModel, IConfig>;
161
+ /**
162
+ * A signal emitting when unread messages change.
163
+ */
164
+ get unreadChanged(): ISignal<IChatModel, number[]>;
165
+ /**
166
+ * A signal emitting when the viewport change.
167
+ */
168
+ get viewportChanged(): ISignal<IChatModel, number[]>;
110
169
  /**
111
170
  * Send a message, to be defined depending on the chosen technology.
112
171
  * Default to no-op.
@@ -115,13 +174,6 @@ export declare class ChatModel implements IChatModel {
115
174
  * @returns whether the message has been sent or not.
116
175
  */
117
176
  addMessage(message: INewMessage): Promise<boolean | void> | boolean | void;
118
- /**
119
- * Optional, to update a message from the chat panel.
120
- *
121
- * @param id - the unique ID of the message.
122
- * @param message - the message to update.
123
- */
124
- updateMessage?(id: string, message: INewMessage): Promise<boolean | void> | boolean | void;
125
177
  /**
126
178
  * Dispose the chat model.
127
179
  */
@@ -155,11 +207,35 @@ export declare class ChatModel implements IChatModel {
155
207
  * @param count - the number of messages to delete.
156
208
  */
157
209
  messagesDeleted(index: number, count: number): void;
210
+ /**
211
+ * Add unread messages to the list.
212
+ * @param indexes - list of new indexes.
213
+ */
214
+ private _addUnreadMessages;
215
+ /**
216
+ * Notifications on unread messages.
217
+ *
218
+ * @param unreadCount - number of unread messages.
219
+ * If the value is 0, existing notification will be deleted.
220
+ * @param canCreate - whether to create a notification if it does not exist.
221
+ * Usually it is used when there are new unread messages, and not when the
222
+ * unread messages count decrease.
223
+ */
224
+ private _notify;
158
225
  private _messages;
226
+ private _unreadMessages;
227
+ private _messagesInViewport;
159
228
  private _id;
229
+ private _name;
160
230
  private _config;
161
231
  private _isDisposed;
232
+ private _commands?;
233
+ private _activeCellManager;
234
+ private _notificationId;
162
235
  private _messagesUpdated;
236
+ private _configChanged;
237
+ private _unreadChanged;
238
+ private _viewportChanged;
163
239
  }
164
240
  /**
165
241
  * The chat model namespace.
@@ -173,5 +249,13 @@ export declare namespace ChatModel {
173
249
  * Initial config for the chat widget.
174
250
  */
175
251
  config?: IConfig;
252
+ /**
253
+ * Commands registry.
254
+ */
255
+ commands?: CommandRegistry;
256
+ /**
257
+ * Active cell manager
258
+ */
259
+ activeCellManager?: IActiveCellManager | null;
176
260
  }
177
261
  }