@jupyter/chat 0.7.0 → 0.8.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/active-cell-manager.js +1 -4
- package/lib/chat-commands/index.d.ts +2 -0
- package/lib/chat-commands/index.js +6 -0
- package/lib/chat-commands/registry.d.ts +28 -0
- package/lib/chat-commands/registry.js +29 -0
- package/lib/chat-commands/types.d.ts +51 -0
- package/lib/chat-commands/types.js +5 -0
- package/lib/components/attachments.d.ts +23 -0
- package/lib/components/attachments.js +44 -0
- package/lib/components/chat-input.d.ts +8 -11
- package/lib/components/chat-input.js +70 -95
- package/lib/components/chat-messages.d.ts +4 -0
- package/lib/components/chat-messages.js +27 -1
- package/lib/components/chat.d.ts +11 -5
- package/lib/components/chat.js +7 -8
- package/lib/components/input/attach-button.d.ts +14 -0
- package/lib/components/input/attach-button.js +45 -0
- package/lib/components/input/index.d.ts +1 -0
- package/lib/components/input/index.js +1 -0
- package/lib/components/input/send-button.d.ts +2 -2
- package/lib/components/input/use-chat-commands.d.ts +19 -0
- package/lib/components/input/use-chat-commands.js +127 -0
- package/lib/context.d.ts +3 -0
- package/lib/context.js +6 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/input-model.d.ts +221 -0
- package/lib/input-model.js +217 -0
- package/lib/model.d.ts +10 -25
- package/lib/model.js +15 -17
- package/lib/registry.d.ts +11 -64
- package/lib/registry.js +4 -72
- package/lib/types.d.ts +19 -38
- package/lib/widgets/chat-widget.js +2 -1
- package/package.json +3 -114
- package/src/active-cell-manager.ts +0 -3
- package/src/chat-commands/index.ts +7 -0
- package/src/chat-commands/registry.ts +60 -0
- package/src/chat-commands/types.ts +67 -0
- package/src/components/attachments.tsx +91 -0
- package/src/components/chat-input.tsx +97 -124
- package/src/components/chat-messages.tsx +36 -3
- package/src/components/chat.tsx +28 -19
- package/src/components/input/attach-button.tsx +68 -0
- package/src/components/input/cancel-button.tsx +1 -0
- package/src/components/input/index.ts +1 -0
- package/src/components/input/send-button.tsx +2 -2
- package/src/components/input/use-chat-commands.tsx +186 -0
- package/src/context.ts +10 -0
- package/src/index.ts +2 -0
- package/src/input-model.ts +406 -0
- package/src/model.ts +24 -35
- package/src/registry.ts +14 -108
- package/src/types.ts +19 -39
- package/src/widgets/chat-widget.tsx +2 -1
- package/style/chat.css +27 -9
- package/style/icons/include-selection.svg +3 -1
- package/style/icons/read.svg +8 -6
- package/style/icons/replace-cell.svg +10 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyter/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "A package that provides UI components that can be used to create a chat in a Jupyterlab extension.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -38,16 +38,7 @@
|
|
|
38
38
|
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
|
|
39
39
|
"clean:lintcache": "rimraf .eslintcache .stylelintcache",
|
|
40
40
|
"clean:all": "jlpm clean:lib && jlpm clean:lintcache",
|
|
41
|
-
"eslint": "jlpm eslint:check --fix",
|
|
42
|
-
"eslint:check": "eslint . --cache --ext .ts,.tsx",
|
|
43
41
|
"install:extension": "jlpm build",
|
|
44
|
-
"lint": "jlpm stylelint && jlpm prettier && jlpm eslint",
|
|
45
|
-
"lint:check": "jlpm stylelint:check && jlpm prettier:check && jlpm eslint:check",
|
|
46
|
-
"prettier": "jlpm prettier:base --write --list-different",
|
|
47
|
-
"prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"",
|
|
48
|
-
"prettier:check": "jlpm prettier:base --check",
|
|
49
|
-
"stylelint": "jlpm stylelint:check --fix",
|
|
50
|
-
"stylelint:check": "stylelint --cache \"style/**/*.css\"",
|
|
51
42
|
"test": "jest --coverage",
|
|
52
43
|
"watch:src": "tsc -w --sourceMap"
|
|
53
44
|
},
|
|
@@ -57,6 +48,8 @@
|
|
|
57
48
|
"@jupyter/react-components": "^0.15.2",
|
|
58
49
|
"@jupyterlab/application": "^4.2.0",
|
|
59
50
|
"@jupyterlab/apputils": "^4.3.0",
|
|
51
|
+
"@jupyterlab/docmanager": "^4.2.0",
|
|
52
|
+
"@jupyterlab/filebrowser": "^4.2.0",
|
|
60
53
|
"@jupyterlab/fileeditor": "^4.2.0",
|
|
61
54
|
"@jupyterlab/notebook": "^4.2.0",
|
|
62
55
|
"@jupyterlab/rendermime": "^4.2.0",
|
|
@@ -78,23 +71,12 @@
|
|
|
78
71
|
"@types/react": "^18.2.0",
|
|
79
72
|
"@types/react-addons-linked-state-mixin": "^0.14.22",
|
|
80
73
|
"@types/react-dom": "^18.2.0",
|
|
81
|
-
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
|
82
|
-
"@typescript-eslint/parser": "^6.1.0",
|
|
83
74
|
"css-loader": "^6.7.1",
|
|
84
|
-
"eslint": "^8.36.0",
|
|
85
|
-
"eslint-config-prettier": "^8.8.0",
|
|
86
|
-
"eslint-plugin-prettier": "^5.0.0",
|
|
87
75
|
"jest": "^29.2.0",
|
|
88
76
|
"npm-run-all": "^4.1.5",
|
|
89
|
-
"prettier": "^3.0.0",
|
|
90
77
|
"rimraf": "^5.0.1",
|
|
91
78
|
"source-map-loader": "^1.0.2",
|
|
92
79
|
"style-loader": "^3.3.1",
|
|
93
|
-
"stylelint": "^15.10.1",
|
|
94
|
-
"stylelint-config-recommended": "^13.0.0",
|
|
95
|
-
"stylelint-config-standard": "^34.0.0",
|
|
96
|
-
"stylelint-csstree-validator": "^3.0.0",
|
|
97
|
-
"stylelint-prettier": "^4.0.0",
|
|
98
80
|
"typescript": "~5.0.2"
|
|
99
81
|
},
|
|
100
82
|
"sideEffects": [
|
|
@@ -104,98 +86,5 @@
|
|
|
104
86
|
"styleModule": "style/index.js",
|
|
105
87
|
"publishConfig": {
|
|
106
88
|
"access": "public"
|
|
107
|
-
},
|
|
108
|
-
"eslintIgnore": [
|
|
109
|
-
"node_modules",
|
|
110
|
-
"dist",
|
|
111
|
-
"coverage",
|
|
112
|
-
"**/*.d.ts",
|
|
113
|
-
"tests",
|
|
114
|
-
"**/__tests__"
|
|
115
|
-
],
|
|
116
|
-
"eslintConfig": {
|
|
117
|
-
"extends": [
|
|
118
|
-
"eslint:recommended",
|
|
119
|
-
"plugin:@typescript-eslint/eslint-recommended",
|
|
120
|
-
"plugin:@typescript-eslint/recommended",
|
|
121
|
-
"plugin:prettier/recommended"
|
|
122
|
-
],
|
|
123
|
-
"parser": "@typescript-eslint/parser",
|
|
124
|
-
"parserOptions": {
|
|
125
|
-
"project": "tsconfig.json",
|
|
126
|
-
"sourceType": "module"
|
|
127
|
-
},
|
|
128
|
-
"plugins": [
|
|
129
|
-
"@typescript-eslint"
|
|
130
|
-
],
|
|
131
|
-
"rules": {
|
|
132
|
-
"@typescript-eslint/naming-convention": [
|
|
133
|
-
"error",
|
|
134
|
-
{
|
|
135
|
-
"selector": "interface",
|
|
136
|
-
"format": [
|
|
137
|
-
"PascalCase"
|
|
138
|
-
],
|
|
139
|
-
"custom": {
|
|
140
|
-
"regex": "^I[A-Z]",
|
|
141
|
-
"match": true
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
],
|
|
145
|
-
"@typescript-eslint/no-unused-vars": [
|
|
146
|
-
"warn",
|
|
147
|
-
{
|
|
148
|
-
"args": "none"
|
|
149
|
-
}
|
|
150
|
-
],
|
|
151
|
-
"@typescript-eslint/no-explicit-any": "off",
|
|
152
|
-
"@typescript-eslint/no-namespace": "off",
|
|
153
|
-
"@typescript-eslint/no-use-before-define": "off",
|
|
154
|
-
"@typescript-eslint/quotes": [
|
|
155
|
-
"error",
|
|
156
|
-
"single",
|
|
157
|
-
{
|
|
158
|
-
"avoidEscape": true,
|
|
159
|
-
"allowTemplateLiterals": false
|
|
160
|
-
}
|
|
161
|
-
],
|
|
162
|
-
"curly": [
|
|
163
|
-
"error",
|
|
164
|
-
"all"
|
|
165
|
-
],
|
|
166
|
-
"eqeqeq": "error",
|
|
167
|
-
"prefer-arrow-callback": "error"
|
|
168
|
-
}
|
|
169
|
-
},
|
|
170
|
-
"prettier": {
|
|
171
|
-
"singleQuote": true,
|
|
172
|
-
"trailingComma": "none",
|
|
173
|
-
"arrowParens": "avoid",
|
|
174
|
-
"endOfLine": "auto",
|
|
175
|
-
"overrides": [
|
|
176
|
-
{
|
|
177
|
-
"files": "package.json",
|
|
178
|
-
"options": {
|
|
179
|
-
"tabWidth": 2
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
]
|
|
183
|
-
},
|
|
184
|
-
"stylelint": {
|
|
185
|
-
"extends": [
|
|
186
|
-
"stylelint-config-recommended",
|
|
187
|
-
"stylelint-config-standard",
|
|
188
|
-
"stylelint-prettier/recommended"
|
|
189
|
-
],
|
|
190
|
-
"plugins": [
|
|
191
|
-
"stylelint-csstree-validator"
|
|
192
|
-
],
|
|
193
|
-
"rules": {
|
|
194
|
-
"csstree/validator": true,
|
|
195
|
-
"property-no-vendor-prefix": null,
|
|
196
|
-
"selector-class-pattern": "^([a-z][A-z\\d]*)(-[A-z\\d]+)*$",
|
|
197
|
-
"selector-no-vendor-prefix": null,
|
|
198
|
-
"value-no-vendor-prefix": null
|
|
199
|
-
}
|
|
200
89
|
}
|
|
201
90
|
}
|
|
@@ -265,9 +265,6 @@ export class ActiveCellManager implements IActiveCellManager {
|
|
|
265
265
|
this._activeCell?.model.stateChanged.connect(this._cellStateChange);
|
|
266
266
|
this._available = !!this._activeCell && this._notebookVisible;
|
|
267
267
|
this._availabilityChanged.emit(this._available);
|
|
268
|
-
this._activeCell?.disposed.connect(() => {
|
|
269
|
-
this._activeCell = null;
|
|
270
|
-
});
|
|
271
268
|
});
|
|
272
269
|
}
|
|
273
270
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Token } from '@lumino/coreutils';
|
|
7
|
+
import { ChatCommand, IChatCommandProvider } from './types';
|
|
8
|
+
import { IInputModel } from '../input-model';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Interface of a chat command registry, which tracks a list of chat command
|
|
12
|
+
* providers. Providers provide a list of commands given a user's partial input,
|
|
13
|
+
* and define how commands are handled when accepted in the chat commands menu.
|
|
14
|
+
*/
|
|
15
|
+
export interface IChatCommandRegistry {
|
|
16
|
+
addProvider(provider: IChatCommandProvider): void;
|
|
17
|
+
getProviders(): IChatCommandProvider[];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Handles a chat command by calling `handleChatCommand()` on the provider
|
|
21
|
+
* corresponding to this chat command.
|
|
22
|
+
*/
|
|
23
|
+
handleChatCommand(command: ChatCommand, inputModel: IInputModel): void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default chat command registry implementation.
|
|
28
|
+
*/
|
|
29
|
+
export class ChatCommandRegistry implements IChatCommandRegistry {
|
|
30
|
+
constructor() {
|
|
31
|
+
this._providers = new Map<string, IChatCommandProvider>();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
addProvider(provider: IChatCommandProvider): void {
|
|
35
|
+
this._providers.set(provider.id, provider);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getProviders(): IChatCommandProvider[] {
|
|
39
|
+
return Array.from(this._providers.values());
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
handleChatCommand(command: ChatCommand, inputModel: IInputModel) {
|
|
43
|
+
const provider = this._providers.get(command.providerId);
|
|
44
|
+
if (!provider) {
|
|
45
|
+
console.error(
|
|
46
|
+
'Error in handling chat command: No command provider has an ID of ' +
|
|
47
|
+
command.providerId
|
|
48
|
+
);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
provider.handleChatCommand(command, inputModel);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private _providers: Map<string, IChatCommandProvider>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const IChatCommandRegistry = new Token<IChatCommandRegistry>(
|
|
59
|
+
'@jupyter/chat:IChatCommandRegistry'
|
|
60
|
+
);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { LabIcon } from '@jupyterlab/ui-components';
|
|
7
|
+
import { IInputModel } from '../input-model';
|
|
8
|
+
|
|
9
|
+
export type ChatCommand = {
|
|
10
|
+
/**
|
|
11
|
+
* The name of the command. This defines what the user should type in the
|
|
12
|
+
* input to have the command appear in the chat commands menu.
|
|
13
|
+
*/
|
|
14
|
+
name: string;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* ID of the provider the command originated from.
|
|
18
|
+
*/
|
|
19
|
+
providerId: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* If set, this will be rendered as the icon for the command in the chat
|
|
23
|
+
* commands menu. Jupyter Chat will choose a default if this is unset.
|
|
24
|
+
*/
|
|
25
|
+
icon?: LabIcon | string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* If set, this will be rendered as the description for the command in the
|
|
29
|
+
* chat commands menu. Jupyter Chat will choose a default if this is unset.
|
|
30
|
+
*/
|
|
31
|
+
description?: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* If set, Jupyter Chat will replace the current word with this string after
|
|
35
|
+
* the command is run from the chat commands menu.
|
|
36
|
+
*
|
|
37
|
+
* If all commands from a provider have this property set, then
|
|
38
|
+
* `handleChatCommands()` can just return on the first line.
|
|
39
|
+
*/
|
|
40
|
+
replaceWith?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Interface of a command provider.
|
|
45
|
+
*/
|
|
46
|
+
export interface IChatCommandProvider {
|
|
47
|
+
/**
|
|
48
|
+
* ID of this command provider.
|
|
49
|
+
*/
|
|
50
|
+
id: string;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Async function which accepts the input model and returns a list of
|
|
54
|
+
* valid chat commands that match the current word. The current word is
|
|
55
|
+
* space-separated word at the user's cursor.
|
|
56
|
+
*/
|
|
57
|
+
getChatCommands(inputModel: IInputModel): Promise<ChatCommand[]>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Function called when a chat command is run by the user through the chat
|
|
61
|
+
* commands menu.
|
|
62
|
+
*/
|
|
63
|
+
handleChatCommand(
|
|
64
|
+
command: ChatCommand,
|
|
65
|
+
inputModel: IInputModel
|
|
66
|
+
): Promise<void>;
|
|
67
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
7
|
+
import CloseIcon from '@mui/icons-material/Close';
|
|
8
|
+
import { Box } from '@mui/material';
|
|
9
|
+
import React, { useContext } from 'react';
|
|
10
|
+
|
|
11
|
+
import { TooltippedButton } from './mui-extras/tooltipped-button';
|
|
12
|
+
import { IAttachment } from '../types';
|
|
13
|
+
import { AttachmentOpenerContext } from '../context';
|
|
14
|
+
|
|
15
|
+
const ATTACHMENTS_CLASS = 'jp-chat-attachments';
|
|
16
|
+
const ATTACHMENT_CLASS = 'jp-chat-attachment';
|
|
17
|
+
const ATTACHMENT_CLICKABLE_CLASS = 'jp-chat-attachment-clickable';
|
|
18
|
+
const REMOVE_BUTTON_CLASS = 'jp-chat-attachment-remove';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The attachments props.
|
|
22
|
+
*/
|
|
23
|
+
export type AttachmentsProps = {
|
|
24
|
+
attachments: IAttachment[];
|
|
25
|
+
onRemove?: (attachment: IAttachment) => void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The Attachments component.
|
|
30
|
+
*/
|
|
31
|
+
export function AttachmentPreviewList(props: AttachmentsProps): JSX.Element {
|
|
32
|
+
return (
|
|
33
|
+
<Box className={ATTACHMENTS_CLASS}>
|
|
34
|
+
{props.attachments.map(attachment => (
|
|
35
|
+
<AttachmentPreview {...props} attachment={attachment} />
|
|
36
|
+
))}
|
|
37
|
+
</Box>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The attachment props.
|
|
43
|
+
*/
|
|
44
|
+
export type AttachmentProps = AttachmentsProps & {
|
|
45
|
+
attachment: IAttachment;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The Attachment component.
|
|
50
|
+
*/
|
|
51
|
+
export function AttachmentPreview(props: AttachmentProps): JSX.Element {
|
|
52
|
+
const remove_tooltip = 'Remove attachment';
|
|
53
|
+
const attachmentOpenerRegistry = useContext(AttachmentOpenerContext);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Box className={ATTACHMENT_CLASS}>
|
|
57
|
+
<span
|
|
58
|
+
className={
|
|
59
|
+
attachmentOpenerRegistry?.get(props.attachment.type)
|
|
60
|
+
? ATTACHMENT_CLICKABLE_CLASS
|
|
61
|
+
: ''
|
|
62
|
+
}
|
|
63
|
+
onClick={() =>
|
|
64
|
+
attachmentOpenerRegistry?.get(props.attachment.type)?.(
|
|
65
|
+
props.attachment
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
>
|
|
69
|
+
{props.attachment.value}
|
|
70
|
+
</span>
|
|
71
|
+
{props.onRemove && (
|
|
72
|
+
<TooltippedButton
|
|
73
|
+
onClick={() => props.onRemove!(props.attachment)}
|
|
74
|
+
tooltip={remove_tooltip}
|
|
75
|
+
buttonProps={{
|
|
76
|
+
size: 'small',
|
|
77
|
+
title: remove_tooltip,
|
|
78
|
+
className: REMOVE_BUTTON_CLASS
|
|
79
|
+
}}
|
|
80
|
+
sx={{
|
|
81
|
+
minWidth: 'unset',
|
|
82
|
+
padding: '0',
|
|
83
|
+
color: 'inherit'
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
<CloseIcon />
|
|
87
|
+
</TooltippedButton>
|
|
88
|
+
)}
|
|
89
|
+
</Box>
|
|
90
|
+
);
|
|
91
|
+
}
|