diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 708ae7e..48b28a8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,15 +65,15 @@ jobs: - name: Package extension run: | set -eux - pip install build packages/jupyterlab-${{ matrix.extension }}-chat - python -m build packages/jupyterlab-${{ matrix.extension }}-chat + pip install build python/jupyterlab-${{ matrix.extension }}-chat + python -m build python/jupyterlab-${{ matrix.extension }}-chat pip uninstall -y "jupyterlab_${{ matrix.extension }}_chat" jupyterlab - name: Upload package uses: actions/upload-artifact@v3 with: name: jupyterlab_${{ matrix.extension }}_chat-artifacts - path: packages/jupyterlab-${{ matrix.extension }}-chat/dist/jupyterlab_${{ matrix.extension }}_chat* + path: python/jupyterlab-${{ matrix.extension }}-chat/dist/jupyterlab_${{ matrix.extension }}_chat* if-no-files-found: error integration-tests: @@ -105,7 +105,7 @@ jobs: python -m pip install "jupyterlab>=4.0.0,<5" jupyterlab_${{ matrix.extension }}_chat*.whl - name: Install dependencies - working-directory: packages/jupyterlab-${{ matrix.extension }}-chat/ui-tests + working-directory: python/jupyterlab-${{ matrix.extension }}-chat/ui-tests env: YARN_ENABLE_IMMUTABLE_INSTALLS: 0 PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 @@ -120,10 +120,10 @@ jobs: - name: Install browser run: jlpm playwright install chromium - working-directory: packages/jupyterlab-${{ matrix.extension }}-chat/ui-tests + working-directory: python/jupyterlab-${{ matrix.extension }}-chat/ui-tests - name: Execute integration tests - working-directory: packages/jupyterlab-${{ matrix.extension }}-chat/ui-tests + working-directory: python/jupyterlab-${{ matrix.extension }}-chat/ui-tests run: | jlpm playwright test --retries=2 @@ -133,8 +133,8 @@ jobs: with: name: jupyterlab_${{ matrix.extension }}_chat-playwright-tests path: | - packages/jupyterlab-${{ matrix.extension }}-chat/ui-tests/test-results - packages/jupyterlab-${{ matrix.extension }}-chat/ui-tests/playwright-report + python/jupyterlab-${{ matrix.extension }}-chat/ui-tests/test-results + python/jupyterlab-${{ matrix.extension }}-chat/ui-tests/playwright-report check_links: name: Check Links diff --git a/.github/workflows/update-integration-tests.yml b/.github/workflows/update-integration-tests.yml index 0e44966..9777721 100644 --- a/.github/workflows/update-integration-tests.yml +++ b/.github/workflows/update-integration-tests.yml @@ -79,11 +79,11 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} # Playwright knows how to start JupyterLab server start_server_script: 'null' - test_folder: packages/jupyterlab-ws-chat/ui-tests + test_folder: python/jupyterlab-ws-chat/ui-tests - uses: jupyterlab/maintainer-tools/.github/actions/update-snapshots@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Playwright knows how to start JupyterLab server start_server_script: 'null' - test_folder: packages/jupyterlab-collaborative-chat/ui-tests + test_folder: python/jupyterlab-collaborative-chat/ui-tests diff --git a/.gitignore b/.gitignore index 5614944..a1ede36 100644 --- a/.gitignore +++ b/.gitignore @@ -7,14 +7,19 @@ node_modules/ *.egg-info/ .ipynb_checkpoints *.tsbuildinfo -jupyter_chat/labextension .jupyter_ystore.db +labextension + # Version file is handled by hatchling -jupyter_chat/_version.py +python/**/_version.py + +# jest test reports +packages/jupyter-chat/junit.xml +packages/jupyterlab-collaborative-chat/junit.xml # Integration tests -ui-tests/test-results/ -ui-tests/playwright-report/ +python/jupyterlab-collaborative-chat/ui-tests/test-results/ +python/jupyterlab-collaborative-chat/ui-tests/playwright-report/ # Created by https://www.gitignore.io/api/python # Edit at https://www.gitignore.io/?templates=python diff --git a/README.md b/README.md index 623dbb7..399bee4 100644 --- a/README.md +++ b/README.md @@ -14,26 +14,36 @@ Many components of this chat project come from [jupyter-ai](https://github.com/j ### Typescript package +#### @jupyter/chat + The typescript package is located in *packages/jupyter-chat* and builds an NPM package named `@jupyter/chat`. This package provides a frontend library (using react), and is intended to be used by a jupyterlab extension to create a chat. +#### jupyterlab-collaborative-chat + +The typescript package is located in *packages/jupyterlab-collaborative-chat* and +builds an NPM package named `jupyterlab-collaborative-chat`. + +This package relies on `@jupyter/chat` and provides a typescript library. +It is intended to be used by a jupyterlab extension to create a collaborative chat. + ### Jupyterlab extensions -#### Chat extension based on shared document: *packages/jupyterlab-collaborative-chat* +#### Chat extension based on shared document: *python/jupyterlab-collaborative-chat* -This extension is an implementation of the `@jupyter/chat` package, relying on -shared document (see [jupyter_ydoc](https://github.com/jupyter-server/jupyter_ydoc)). +This extension is an implementation of the `jupyter-collaborative-chat` package, relying +on shared document (see [jupyter_ydoc](https://github.com/jupyter-server/jupyter_ydoc)). It is composed of: - a Python package named `jupyterlab_collaborative_chat`, which register the `YChat` shared document in jupyter_ydoc -- a NPM package named `jupyterlab-collaborative-chat`. +- a NPM package named `jupyterlab-collaborative-chat-extension`. -#### Chat extension based on websocket: *packages/jupyterlab-ws-chat* +#### Chat extension based on websocket: *python/jupyterlab-ws-chat* This extension is an implementation of the `@jupyter/chat` package, relying on websocket for the communication between server and front end. diff --git a/docs/source/developers/contributing/jupyterlab-collaborative-chat.md b/docs/source/developers/contributing/jupyterlab-collaborative-chat.md index a1a494f..0d87fc2 100644 --- a/docs/source/developers/contributing/jupyterlab-collaborative-chat.md +++ b/docs/source/developers/contributing/jupyterlab-collaborative-chat.md @@ -20,7 +20,7 @@ The following commands install the extension in development mode: ./scripts/install.sh collaborative # Symlink the assets -jupyter labextension develop --overwrite packages/jupyterlab-collaborative-chat +jupyter labextension develop --overwrite python/jupyterlab-collaborative-chat ``` To uninstall it, run: @@ -44,27 +44,27 @@ jlpm build:collaborative ### Unit tests -There are a few unit tests in *packages/jupyterlab-collaborative-chat/src/\_\_tests\_\_*. +There are a few unit tests in *python/jupyterlab-collaborative-chat/src/\_\_tests\_\_*. They make use of [jest](https://jestjs.io/). The following commands run them: ```bash -cd ./packages/jupyterlab-collaborative-chat +cd ./python/jupyterlab-collaborative-chat jlpm test ``` ### Integration tests -The integration tests are located in *packages/jupyterlab-collaborative-chat/ui-tests*. +The integration tests are located in *python/jupyterlab-collaborative-chat/ui-tests*. They make use of [playwright](https://playwright.dev/). The following commands run them: ```bash -cd ./packages/jupyterlab-collaborative-chat/ui-tests +cd ./python/jupyterlab-collaborative-chat/ui-tests # Install the tests dependencies jlpm install diff --git a/docs/source/developers/contributing/jupyterlab-ws-chat.md b/docs/source/developers/contributing/jupyterlab-ws-chat.md index de1601b..a51362a 100644 --- a/docs/source/developers/contributing/jupyterlab-ws-chat.md +++ b/docs/source/developers/contributing/jupyterlab-ws-chat.md @@ -20,7 +20,7 @@ The following commands install the extension in development mode: ./scripts/install.sh ws # Symlink the assets -jupyter labextension develop --overwrite packages/jupyterlab-ws-chat +jupyter labextension develop --overwrite python/jupyterlab-ws-chat ``` To uninstall it, run: diff --git a/package.json b/package.json index 4574006..cc5983b 100644 --- a/package.json +++ b/package.json @@ -22,13 +22,15 @@ "url": "https://github.com/jupyterlab/jupyter-chat.git" }, "workspaces": [ - "packages/*" + "packages/*", + "python/jupyterlab-collaborative-chat", + "python/jupyterlab-ws-chat" ], "scripts": { "build": "lerna run build --stream", "build:core": "lerna run build --stream --scope \"@jupyter/chat\"", - "build:collaborative": "lerna run build --scope=jupyterlab-collaborative-chat --include-filtered-dependencies", - "build:ws": "lerna run build --scope=jupyterlab-ws-chat --include-filtered-dependencies", + "build:collaborative": "lerna run build --scope=jupyterlab-collaborative-chat-extension --include-filtered-dependencies", + "build:ws": "lerna run build --scope=jupyterlab-ws-chat-extension --include-filtered-dependencies", "build:prod": "lerna run build:prod --stream", "clean": "lerna run clean", "clean:all": "lerna run clean:all", diff --git a/packages/jupyter-chat/babel.config.js b/packages/jupyter-chat/babel.config.js index bf69a46..eb2198a 100644 --- a/packages/jupyter-chat/babel.config.js +++ b/packages/jupyter-chat/babel.config.js @@ -3,4 +3,4 @@ * Distributed under the terms of the Modified BSD License. */ -module.exports = require('@jupyterlab/testutils/lib/babel.config'); +module.exports = require('@jupyterlab/testing/lib/babel-config'); diff --git a/packages/jupyter-chat/jest.config.js b/packages/jupyter-chat/jest.config.js index 4f6b85b..afdc40c 100644 --- a/packages/jupyter-chat/jest.config.js +++ b/packages/jupyter-chat/jest.config.js @@ -3,7 +3,7 @@ * Distributed under the terms of the Modified BSD License. */ -const jestJupyterLab = require('@jupyterlab/testutils/lib/jest-config'); +const jestJupyterLab = require('@jupyterlab/testing/lib/jest-config'); const esModules = [ '@codemirror', diff --git a/packages/jupyter-chat/package.json b/packages/jupyter-chat/package.json index cb68689..f11b55e 100644 --- a/packages/jupyter-chat/package.json +++ b/packages/jupyter-chat/package.json @@ -70,6 +70,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@jupyterlab/testing": "^4.2.0", "@types/jest": "^29.2.0", "@types/json-schema": "^7.0.11", "@types/react": "^18.2.0", @@ -102,20 +103,6 @@ "publishConfig": { "access": "public" }, - "jupyterlab": { - "discovery": { - "server": { - "managers": [ - "pip" - ], - "base": { - "name": "jupyter_chat" - } - } - }, - "extension": false, - "schemaDir": "schema" - }, "eslintIgnore": [ "node_modules", "dist", diff --git a/packages/jupyterlab-collaborative-chat/.gitignore b/packages/jupyterlab-collaborative-chat/.gitignore deleted file mode 100644 index 6f5b435..0000000 --- a/packages/jupyterlab-collaborative-chat/.gitignore +++ /dev/null @@ -1,125 +0,0 @@ -*.bundle.* -lib/ -node_modules/ -*.log -.eslintcache -.stylelintcache -*.egg-info/ -.ipynb_checkpoints -*.tsbuildinfo -jupyterlab_collaborative_chat/labextension -# Version file is handled by hatchling -jupyterlab_collaborative_chat/_version.py - -# Integration tests -ui-tests/test-results/ -ui-tests/playwright-report/ - -# Created by https://www.gitignore.io/api/python -# Edit at https://www.gitignore.io/?templates=python - -### Python ### -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage/ -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# End of https://www.gitignore.io/api/python - -# OSX files -.DS_Store - -# Yarn cache -.yarn/ diff --git a/packages/jupyterlab-collaborative-chat/.yarnrc.yml b/packages/jupyterlab-collaborative-chat/.yarnrc.yml deleted file mode 100644 index 3186f3f..0000000 --- a/packages/jupyterlab-collaborative-chat/.yarnrc.yml +++ /dev/null @@ -1 +0,0 @@ -nodeLinker: node-modules diff --git a/packages/jupyterlab-collaborative-chat/babel.config.js b/packages/jupyterlab-collaborative-chat/babel.config.js index bf69a46..eb2198a 100644 --- a/packages/jupyterlab-collaborative-chat/babel.config.js +++ b/packages/jupyterlab-collaborative-chat/babel.config.js @@ -3,4 +3,4 @@ * Distributed under the terms of the Modified BSD License. */ -module.exports = require('@jupyterlab/testutils/lib/babel.config'); +module.exports = require('@jupyterlab/testing/lib/babel-config'); diff --git a/packages/jupyterlab-collaborative-chat/jest.config.js b/packages/jupyterlab-collaborative-chat/jest.config.js index f6c4a5e..c74e0e6 100644 --- a/packages/jupyterlab-collaborative-chat/jest.config.js +++ b/packages/jupyterlab-collaborative-chat/jest.config.js @@ -3,7 +3,7 @@ * Distributed under the terms of the Modified BSD License. */ -const jestJupyterLab = require('@jupyterlab/testutils/lib/jest-config'); +const jestJupyterLab = require('@jupyterlab/testing/lib/jest-config'); const esModules = [ '@codemirror', diff --git a/packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/test_handlers.py b/packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/test_handlers.py deleted file mode 100644 index 263f0e3..0000000 --- a/packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/test_handlers.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) Jupyter Development Team. -# Distributed under the terms of the Modified BSD License. - -import json - - -async def test_get_example(jp_fetch): - # When - response = await jp_fetch("jupyterlab-collaborative-chat", "get-example") - - # Then - assert response.code == 200 - payload = json.loads(response.body) - assert payload == { - "data": "This is /jupyterlab-collaborative-chat/get-example endpoint!" - } \ No newline at end of file diff --git a/packages/jupyterlab-collaborative-chat/package.json b/packages/jupyterlab-collaborative-chat/package.json index b300d0d..b63d288 100644 --- a/packages/jupyterlab-collaborative-chat/package.json +++ b/packages/jupyterlab-collaborative-chat/package.json @@ -1,7 +1,7 @@ { "name": "jupyterlab-collaborative-chat", "version": "0.3.1", - "description": "A chat extension based on shared documents", + "description": "The library to build a chat based on shared document", "keywords": [ "jupyter", "jupyterlab", @@ -19,8 +19,7 @@ "files": [ "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", "style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}", - "src/**/*.{ts,tsx}", - "schema/*.json" + "src/**/*.{ts,tsx}" ], "main": "lib/index.js", "types": "lib/index.d.ts", @@ -30,17 +29,14 @@ "url": "https://github.com/jupyterlab/jupyter-chat.git" }, "scripts": { - "build": "jlpm build:lib && jlpm build:labextension:dev", - "build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension", - "build:labextension": "jupyter labextension build .", - "build:labextension:dev": "jupyter labextension build --development True .", + "build": "jlpm build:lib", + "build:prod": "jlpm clean && jlpm build:lib:prod", "build:lib": "tsc --sourceMap", "build:lib:prod": "tsc", "clean": "jlpm clean:lib", "clean:lib": "rimraf lib tsconfig.tsbuildinfo", "clean:lintcache": "rimraf .eslintcache .stylelintcache", - "clean:labextension": "rimraf jupyterlab_collaborative_chat/labextension jupyterlab_collaborative_chat/_version.py", - "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache", + "clean:all": "jlpm clean:lib && jlpm clean:lintcache", "eslint": "jlpm eslint:check --fix", "eslint:check": "eslint . --cache --ext .ts,.tsx", "install:extension": "jlpm build", @@ -52,9 +48,7 @@ "stylelint": "jlpm stylelint:check --fix", "stylelint:check": "stylelint --cache \"style/**/*.css\"", "test": "jest --coverage", - "watch": "run-p watch:src watch:labextension", - "watch:src": "tsc -w --sourceMap", - "watch:labextension": "jupyter labextension watch ." + "watch:src": "tsc -w --sourceMap" }, "dependencies": { "@jupyter/chat": "^0.3.1", @@ -81,8 +75,7 @@ "yjs": "^13.5.40" }, "devDependencies": { - "@jupyterlab/builder": "^4.2.0", - "@jupyterlab/testutils": "^4.2.0", + "@jupyterlab/testing": "^4.2.0", "@types/jest": "^29.2.0", "@types/json-schema": "^7.0.11", "@types/react": "^18.2.0", @@ -116,27 +109,6 @@ "publishConfig": { "access": "public" }, - "jupyterlab": { - "discovery": { - "server": { - "managers": [ - "pip" - ], - "base": { - "name": "jupyterlab_collaborative_chat" - } - } - }, - "extension": true, - "outputDir": "jupyterlab_collaborative_chat/labextension", - "schemaDir": "schema", - "sharedPackages": { - "@jupyter/docprovider": { - "bundled": true, - "singleton": true - } - } - }, "eslintIgnore": [ "node_modules", "dist", diff --git a/packages/jupyterlab-collaborative-chat/src/index.ts b/packages/jupyterlab-collaborative-chat/src/index.ts index bbefa6e..bffa5be 100644 --- a/packages/jupyterlab-collaborative-chat/src/index.ts +++ b/packages/jupyterlab-collaborative-chat/src/index.ts @@ -3,640 +3,8 @@ * Distributed under the terms of the Modified BSD License. */ -import { - ActiveCellManager, - AutocompletionRegistry, - IActiveCellManager, - IAutocompletionRegistry, - chatIcon, - readIcon -} from '@jupyter/chat'; -import { - ICollaborativeDrive, - SharedDocumentFactory -} from '@jupyter/docprovider'; -import { - ILayoutRestorer, - JupyterFrontEnd, - JupyterFrontEndPlugin -} from '@jupyterlab/application'; -import { - ICommandPalette, - IThemeManager, - IToolbarWidgetRegistry, - InputDialog, - WidgetTracker, - createToolbarFactory, - showErrorMessage -} from '@jupyterlab/apputils'; -import { PathExt } from '@jupyterlab/coreutils'; -import { DocumentRegistry } from '@jupyterlab/docregistry'; -import { ILauncher } from '@jupyterlab/launcher'; -import { INotebookTracker } from '@jupyterlab/notebook'; -import { IObservableList } from '@jupyterlab/observables'; -import { IRenderMimeRegistry } from '@jupyterlab/rendermime'; -import { Contents } from '@jupyterlab/services'; -import { ISettingRegistry } from '@jupyterlab/settingregistry'; -import { ITranslator, nullTranslator } from '@jupyterlab/translation'; -import { launchIcon } from '@jupyterlab/ui-components'; - -import { - WidgetConfig, - ChatWidgetFactory, - CollaborativeChatModelFactory -} from './factory'; -import { CollaborativeChatModel } from './model'; -import { - chatFileType, - CommandIDs, - IChatPanel, - IChatFactory, - IActiveCellManagerToken -} from './token'; -import { ChatPanel, CollaborativeChatPanel } from './widget'; -import { YChat } from './ychat'; - -const FACTORY = 'Chat'; - -const pluginIds = { - activeCellManager: 'jupyterlab-collaborative-chat:activeCellManager', - autocompletionRegistry: - 'jupyterlab-collaborative-chat:autocompletionRegistry', - chatCommands: 'jupyterlab-collaborative-chat:commands', - docFactories: 'jupyterlab-collaborative-chat:factory', - chatPanel: 'jupyterlab-collaborative-chat:chat-panel' -}; - -/** - * Extension providing the autocompletion registry. - */ -const autocompletionPlugin: JupyterFrontEndPlugin = { - id: pluginIds.autocompletionRegistry, - description: 'An autocompletion registry', - autoStart: true, - provides: IAutocompletionRegistry, - activate: (app: JupyterFrontEnd): IAutocompletionRegistry => { - return new AutocompletionRegistry(); - } -}; - -/** - * Extension registering the chat file type. - */ -const docFactories: JupyterFrontEndPlugin = { - id: pluginIds.docFactories, - description: 'A document factories for collaborative chat', - autoStart: true, - requires: [IRenderMimeRegistry], - optional: [ - IActiveCellManagerToken, - IAutocompletionRegistry, - ICollaborativeDrive, - ILayoutRestorer, - ISettingRegistry, - IThemeManager, - IToolbarWidgetRegistry, - ITranslator - ], - provides: IChatFactory, - activate: ( - app: JupyterFrontEnd, - rmRegistry: IRenderMimeRegistry, - activeCellManager: IActiveCellManager | null, - autocompletionRegistry: IAutocompletionRegistry, - drive: ICollaborativeDrive | null, - restorer: ILayoutRestorer | null, - settingRegistry: ISettingRegistry | null, - themeManager: IThemeManager | null, - toolbarRegistry: IToolbarWidgetRegistry | null, - translator_: ITranslator | null - ): IChatFactory => { - const translator = translator_ ?? nullTranslator; - - // Declare the toolbar factory. - let toolbarFactory: - | (( - widget: CollaborativeChatPanel - ) => - | DocumentRegistry.IToolbarItem[] - | IObservableList) - | undefined; - - /** - * Load the settings for the chat widgets. - */ - let sendWithShiftEnter = false; - let stackMessages = true; - let unreadNotifications = true; - let enableCodeToolbar = true; - function loadSetting(setting: ISettingRegistry.ISettings): void { - // Read the settings and convert to the correct type - sendWithShiftEnter = setting.get('sendWithShiftEnter') - .composite as boolean; - stackMessages = setting.get('stackMessages').composite as boolean; - unreadNotifications = setting.get('unreadNotifications') - .composite as boolean; - enableCodeToolbar = setting.get('enableCodeToolbar').composite as boolean; - widgetConfig.config = { - sendWithShiftEnter, - stackMessages, - unreadNotifications, - enableCodeToolbar - }; - } - - if (settingRegistry) { - // Create the main area widget toolbar factory. - if (toolbarRegistry) { - toolbarFactory = createToolbarFactory( - toolbarRegistry, - settingRegistry, - FACTORY, - pluginIds.docFactories, - translator - ); - } - - // Wait for the application to be restored and - // for the settings to be loaded - Promise.all([app.restored, settingRegistry.load(pluginIds.docFactories)]) - .then(([, setting]) => { - // Read the settings - loadSetting(setting); - - // Listen for the plugin setting changes - setting.changed.connect(loadSetting); - }) - .catch(reason => { - console.error( - `Something went wrong when reading the settings.\n${reason}` - ); - }); - } - - /** - * The chat config object. - */ - const widgetConfig = new WidgetConfig({ - sendWithShiftEnter, - stackMessages, - unreadNotifications, - enableCodeToolbar - }); - - // Namespace for the tracker - const namespace = 'chat'; - - // Creating the tracker for the document - const tracker = new WidgetTracker({ namespace }); - - app.docRegistry.addFileType(chatFileType); - - if (drive) { - const chatFactory: SharedDocumentFactory = () => { - return YChat.create(); - }; - drive.sharedModelFactory.registerDocumentFactory('chat', chatFactory); - } - - app.serviceManager.ready - .then(() => { - const user = app.serviceManager.user.identity; - // Creating and registering the model factory for our custom DocumentModel - const modelFactory = new CollaborativeChatModelFactory({ - user, - widgetConfig, - commands: app.commands, - activeCellManager - }); - app.docRegistry.addModelFactory(modelFactory); - }) - .catch(e => - console.error( - 'The collaborative chat model factory is not initialized', - e - ) - ); - - // Creating the widget factory to register it so the document manager knows about - // our new DocumentWidget - const widgetFactory = new ChatWidgetFactory({ - name: FACTORY, - label: 'Chat', - modelName: 'chat', - fileTypes: ['chat'], - defaultFor: ['chat'], - themeManager, - rmRegistry, - toolbarFactory, - translator, - autocompletionRegistry - }); - - // Add the widget to the tracker when it's created - widgetFactory.widgetCreated.connect((sender, widget) => { - // Notify the instance tracker if restore data needs to update. - widget.context.pathChanged.connect(() => { - tracker.save(widget); - }); - tracker.add(widget); - - // Update the 'markAsRead' command status when the unread changed. - widget.model.unreadChanged.connect(() => - app.commands.notifyCommandChanged(CommandIDs.markAsRead) - ); - }); - - // Registering the widget factory - app.docRegistry.addWidgetFactory(widgetFactory); - - // Handle state restoration. - if (restorer) { - void restorer.restore(tracker, { - command: 'docmanager:open', - args: panel => ({ path: panel.context.path, factory: FACTORY }), - name: panel => panel.context.path, - when: app.serviceManager.ready - }); - } - - return { widgetConfig, tracker }; - } -}; - -/** - * Extension providing the commands, menu and laucher. - */ -const chatCommands: JupyterFrontEndPlugin = { - id: pluginIds.chatCommands, - description: 'The commands to create or open a chat', - autoStart: true, - requires: [ICollaborativeDrive, IChatFactory], - optional: [IActiveCellManagerToken, IChatPanel, ICommandPalette, ILauncher], - activate: ( - app: JupyterFrontEnd, - drive: ICollaborativeDrive, - factory: IChatFactory, - activeCellManager: IActiveCellManager | null, - chatPanel: ChatPanel | null, - commandPalette: ICommandPalette | null, - launcher: ILauncher | null - ) => { - const { commands } = app; - const { tracker, widgetConfig } = factory; - /** - * Command to create a new chat. - * - * args: - * name - optional, the name of the chat to create. - * Open a dialog if not provided. - * inSidePanel - optional (default to false). - * Whether to open the chat in side panel or in main area. - * isPalette - optional (default to false). - * Whether the command is in commands palette or not. - */ - commands.addCommand(CommandIDs.createChat, { - label: args => (args.isPalette ? 'Create a new chat' : 'Chat'), - caption: 'Create a chat', - icon: args => (args.isPalette ? undefined : chatIcon), - execute: async args => { - const inSidePanel: boolean = (args.inSidePanel as boolean) ?? false; - let name: string | null = (args.name as string) ?? null; - let filepath = ''; - if (!name) { - name = ( - await InputDialog.getText({ - label: 'Name', - placeholder: 'untitled', - title: 'Create a new chat' - }) - ).value; - } - // no-op if the dialog has been cancelled. - // Fill the filepath if the dialog has been validated with content, - // otherwise create a new untitled chat (empty filepath). - if (name === null) { - return; - } else if (name) { - if (name.endsWith(chatFileType.extensions[0])) { - filepath = name; - } else { - filepath = `${name}${chatFileType.extensions[0]}`; - } - } - - let fileExist = true; - if (filepath) { - await drive.get(filepath, { content: false }).catch(() => { - fileExist = false; - }); - } else { - fileExist = false; - } - - // Create a new file if it does not exists - if (!fileExist) { - // Create a new untitled chat. - let model: Contents.IModel | null = await drive.newUntitled({ - type: 'file', - ext: chatFileType.extensions[0] - }); - // Rename it if a name has been provided. - if (filepath) { - model = await drive.rename(model.path, filepath); - } - - if (!model) { - showErrorMessage( - 'Error creating a chat', - 'An error occured while creating the chat' - ); - return ''; - } - filepath = model.path; - } - - if (commands.hasCommand(CommandIDs.openChat)) { - return commands.execute(CommandIDs.openChat, { - filepath, - inSidePanel - }); - } else { - commands.execute('docmanager:open', { - path: `RTC:${filepath}`, - factory: FACTORY - }); - } - } - }); - - // Add the command to the palette - if (commandPalette) { - commandPalette.addItem({ - category: 'Chat', - command: CommandIDs.createChat, - args: { isPalette: true } - }); - } - - // Add the create command to the launcher - if (launcher) { - launcher.add({ - command: CommandIDs.createChat, - category: 'Chat', - rank: 1 - }); - } - - // The command to mark the chat as read. - commands.addCommand(CommandIDs.markAsRead, { - caption: 'Mark chat as read', - icon: readIcon, - isEnabled: () => - tracker.currentWidget !== null && - tracker.currentWidget === app.shell.currentWidget && - tracker.currentWidget.model.unreadMessages.length > 0, - execute: async args => { - const widget = app.shell.currentWidget; - // Ensure widget is a CollaborativeChatPanel and is in main area - if ( - !widget || - !(widget instanceof CollaborativeChatPanel) || - !Array.from(app.shell.widgets('main')).includes(widget) - ) { - console.error( - `The command '${CommandIDs.markAsRead}' should be executed from the toolbar button only` - ); - return; - } - widget.model.unreadMessages = []; - } - }); - - // Update the 'markAsRead' command status when the current widget changes. - tracker.currentChanged.connect(() => { - commands.notifyCommandChanged(CommandIDs.markAsRead); - }); - - app.serviceManager.ready - .then(() => { - const user = app.serviceManager.user.identity; - /* - * Command to open a chat. - * - * args: - * filepath - the chat file to open. - */ - commands.addCommand(CommandIDs.openChat, { - label: 'Open a chat', - execute: async args => { - const inSidePanel: boolean = (args.inSidePanel as boolean) ?? false; - let filepath: string | null = (args.filepath as string) ?? null; - if (filepath === null) { - filepath = ( - await InputDialog.getText({ - label: 'File path', - placeholder: '/path/to/the/chat/file', - title: 'Path of the chat' - }) - ).value; - } - - if (!filepath) { - return; - } - - let fileExist = true; - await drive.get(filepath, { content: false }).catch(() => { - fileExist = false; - }); - - if (!fileExist) { - showErrorMessage( - 'Error opening chat', - `'${filepath}' is not a valid path` - ); - return; - } - - if (inSidePanel && chatPanel) { - // The chat is opened in the chat panel. - app.shell.activateById(chatPanel.id); - const model = await drive.get(filepath); - - /** - * Create a share model from the chat file - */ - const sharedModel = drive.sharedModelFactory.createNew({ - path: model.path, - format: model.format, - contentType: chatFileType.contentType, - collaborative: true - }) as YChat; - - /** - * Initialize the chat model with the share model - */ - const chat = new CollaborativeChatModel({ - user, - sharedModel, - widgetConfig, - commands: app.commands, - activeCellManager - }); - - /** - * Add a chat widget to the side panel. - */ - chatPanel.addChat( - chat, - PathExt.basename(model.name, chatFileType.extensions[0]) - ); - } else { - // The chat is opened in the main area - commands.execute('docmanager:open', { - path: `RTC:${filepath}`, - factory: FACTORY - }); - } - } - }); - - // Add the command to the palette - if (commandPalette) { - commandPalette.addItem({ - category: 'Chat', - command: CommandIDs.openChat - }); - } - }) - .catch(e => - console.error('The command to open a chat is not initialized\n', e) - ); - } -}; - -/* - * Extension providing a chat panel. - */ -const chatPanel: JupyterFrontEndPlugin = { - id: pluginIds.chatPanel, - description: 'A chat extension for Jupyter', - autoStart: true, - provides: IChatPanel, - requires: [ICollaborativeDrive, IRenderMimeRegistry], - optional: [ - IAutocompletionRegistry, - ILayoutRestorer, - INotebookTracker, - IThemeManager - ], - activate: ( - app: JupyterFrontEnd, - drive: ICollaborativeDrive, - rmRegistry: IRenderMimeRegistry, - autocompletionRegistry: IAutocompletionRegistry, - restorer: ILayoutRestorer | null, - notebookTracker: INotebookTracker, - themeManager: IThemeManager | null - ): ChatPanel => { - const { commands } = app; - - /** - * Add Chat widget to left sidebar - */ - const chatPanel = new ChatPanel({ - commands, - drive, - rmRegistry, - themeManager, - autocompletionRegistry - }); - chatPanel.id = 'JupyterCollaborationChat:sidepanel'; - chatPanel.title.icon = chatIcon; - chatPanel.title.caption = 'Jupyter Chat'; // TODO: i18n/ - - app.shell.add(chatPanel, 'left', { - rank: 2000 - }); - - if (restorer) { - restorer.add(chatPanel, 'jupyter-chat'); - } - - // Use events system to watch changes on files. - const schemaID = - 'https://events.jupyter.org/jupyter_server/contents_service/v1'; - const actions = ['create', 'delete', 'rename']; - app.serviceManager.events.stream.connect((_, emission) => { - if (emission.schema_id === schemaID) { - const action = emission.action as string; - if (actions.includes(action)) { - chatPanel.updateChatNames(); - } - } - }); - - /* - * Command to move a chat from the main area to the side panel. - * - */ - commands.addCommand(CommandIDs.moveToSide, { - label: 'Move the chat to the side panel', - caption: 'Move the chat to the side panel', - icon: launchIcon, - isEnabled: () => commands.hasCommand(CommandIDs.openChat), - execute: async () => { - const widget = app.shell.currentWidget; - // Ensure widget is a CollaborativeChatPanel and is in main area - if ( - !widget || - !(widget instanceof CollaborativeChatPanel) || - !Array.from(app.shell.widgets('main')).includes(widget) - ) { - console.error( - `The command '${CommandIDs.moveToSide}' should be executed from the toolbar button only` - ); - return; - } - // Remove potential drive prefix - const filepath = widget.context.path.split(':').pop(); - commands.execute(CommandIDs.openChat, { - filepath, - inSidePanel: true - }); - widget.dispose(); - } - }); - - return chatPanel; - } -}; - -/** - * Extension providing the active cell manager. - */ -const activeCellManager: JupyterFrontEndPlugin = { - id: pluginIds.activeCellManager, - description: 'the active cell manager plugin', - autoStart: true, - requires: [INotebookTracker], - provides: IActiveCellManagerToken, - activate: ( - app: JupyterFrontEnd, - notebookTracker: INotebookTracker - ): IActiveCellManager => { - return new ActiveCellManager({ - tracker: notebookTracker, - shell: app.shell - }); - } -}; - -export default [ - activeCellManager, - autocompletionPlugin, - chatCommands, - docFactories, - chatPanel -]; +export * from './factory'; +export * from './model'; +export * from './token'; +export * from './widget'; +export * from './ychat'; diff --git a/packages/jupyterlab-ws-chat/.gitignore b/packages/jupyterlab-ws-chat/.gitignore deleted file mode 100644 index 6e882c3..0000000 --- a/packages/jupyterlab-ws-chat/.gitignore +++ /dev/null @@ -1,125 +0,0 @@ -*.bundle.* -lib/ -node_modules/ -*.log -.eslintcache -.stylelintcache -*.egg-info/ -.ipynb_checkpoints -*.tsbuildinfo -jupyterlab_ws_chat/labextension -# Version file is handled by hatchling -jupyterlab_ws_chat/_version.py - -# Integration tests -ui-tests/test-results/ -ui-tests/playwright-report/ - -# Created by https://www.gitignore.io/api/python -# Edit at https://www.gitignore.io/?templates=python - -### Python ### -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage/ -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# End of https://www.gitignore.io/api/python - -# OSX files -.DS_Store - -# Yarn cache -.yarn/ diff --git a/packages/jupyterlab-ws-chat/jest.config.js b/packages/jupyterlab-ws-chat/jest.config.js deleted file mode 100644 index 4f6b85b..0000000 --- a/packages/jupyterlab-ws-chat/jest.config.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) Jupyter Development Team. - * Distributed under the terms of the Modified BSD License. - */ - -const jestJupyterLab = require('@jupyterlab/testutils/lib/jest-config'); - -const esModules = [ - '@codemirror', - '@microsoft', - '@jupyter/react-components', - '@jupyter/web-components', - '@jupyter/ydoc', - '@jupyterlab/', - 'exenv-es6', - 'lib0', - 'nanoid', - 'vscode-ws-jsonrpc', - 'y-protocols', - 'y-websocket', - 'yjs' -].join('|'); - -const baseConfig = jestJupyterLab(__dirname); - -module.exports = { - ...baseConfig, - automock: false, - collectCoverageFrom: [ - 'src/**/*.{ts,tsx}', - '!src/**/*.d.ts', - '!src/**/.ipynb_checkpoints/*' - ], - coverageReporters: ['lcov', 'text'], - testRegex: 'src/.*/.*.spec.ts[x]?$', - transformIgnorePatterns: [`/node_modules/(?!${esModules}).+`] -}; diff --git a/packages/jupyterlab-ws-chat/jupyter-config/nb-config/jupyter_chat.json b/packages/jupyterlab-ws-chat/jupyter-config/nb-config/jupyter_chat.json deleted file mode 100644 index f4818e7..0000000 --- a/packages/jupyterlab-ws-chat/jupyter-config/nb-config/jupyter_chat.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "NotebookApp": { - "nbserver_extensions": { - "jupyterlab_ws_chat": true - } - } -} diff --git a/pyproject.toml b/pyproject.toml index 7d806ad..2a0e9ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,8 +37,8 @@ fields = ["description", "authors", "urls"] [tool.jupyter-releaser.options] version-cmd = "cd ../.. && python scripts/bump_version.py --force --skip-if-dirty" python_packages = [ - "packages/jupyterlab-collaborative-chat", - "packages/jupyterlab-ws-chat" + "python/jupyterlab-collaborative-chat", + "python/jupyterlab-ws-chat" ] [tool.jupyter-releaser.hooks] diff --git a/packages/jupyterlab-collaborative-chat/.copier-answers.yml b/python/jupyterlab-collaborative-chat/.copier-answers.yml similarity index 90% rename from packages/jupyterlab-collaborative-chat/.copier-answers.yml rename to python/jupyterlab-collaborative-chat/.copier-answers.yml index 2a2965e..bbfa1c0 100644 --- a/packages/jupyterlab-collaborative-chat/.copier-answers.yml +++ b/python/jupyterlab-collaborative-chat/.copier-answers.yml @@ -8,7 +8,7 @@ file_extension: '' has_binder: true has_settings: true kind: server -labextension_name: jupyterlab-collaborative-chat +labextension_name: jupyterlab-collaborative-chat-extension mimetype: '' mimetype_name: '' project_short_description: A chat extension based on shared documents diff --git a/packages/jupyterlab-collaborative-chat/.prettierignore b/python/jupyterlab-collaborative-chat/.prettierignore similarity index 100% rename from packages/jupyterlab-collaborative-chat/.prettierignore rename to python/jupyterlab-collaborative-chat/.prettierignore diff --git a/packages/jupyterlab-collaborative-chat/CHANGELOG.md b/python/jupyterlab-collaborative-chat/CHANGELOG.md similarity index 100% rename from packages/jupyterlab-collaborative-chat/CHANGELOG.md rename to python/jupyterlab-collaborative-chat/CHANGELOG.md diff --git a/packages/jupyterlab-collaborative-chat/LICENSE b/python/jupyterlab-collaborative-chat/LICENSE similarity index 100% rename from packages/jupyterlab-collaborative-chat/LICENSE rename to python/jupyterlab-collaborative-chat/LICENSE diff --git a/packages/jupyterlab-collaborative-chat/README.md b/python/jupyterlab-collaborative-chat/README.md similarity index 83% rename from packages/jupyterlab-collaborative-chat/README.md rename to python/jupyterlab-collaborative-chat/README.md index 62eba39..1a7e1d9 100644 --- a/packages/jupyterlab-collaborative-chat/README.md +++ b/python/jupyterlab-collaborative-chat/README.md @@ -1,10 +1,11 @@ # jupyterlab_collaborative_chat [![Github Actions Status](https://github.com/jupyterlab/jupyter-chat/workflows/Build/badge.svg)](https://github.com/jupyterlab/jupyter-chat/actions/workflows/build.yml)[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jupyterlab/jupyter-chat/main?urlpath=lab) -A chat extension based on shared documents + +A chat extension based on shared documents. This extension is composed of a Python package named `jupyterlab_collaborative_chat` -for the server extension and a NPM package named `jupyterlab-collaborative-chat` +for the server extension and a NPM package named `jupyterlab-collaborative-chat-extension` for the frontend extension. This extension registers a `YChat` shared document, and associate the document to a @@ -65,8 +66,6 @@ The `jlpm` command is JupyterLab's pinned version of pip install -e ".[test]" # Link your development version of the extension with JupyterLab jupyter labextension develop . --overwrite -# Server extension must be manually installed in develop mode -jupyter server extension enable jupyterlab_collaborative_chat # Rebuild extension Typescript source after making changes jlpm build ``` @@ -91,35 +90,15 @@ jupyter lab build --minimize=False ### Development uninstall ```bash -# Server extension must be manually disabled in develop mode -jupyter server extension disable jupyterlab_collaborative_chat pip uninstall jupyterlab_collaborative_chat ``` In development mode, you will also need to remove the symlink created by `jupyter labextension develop` command. To find its location, you can run `jupyter labextension list` to figure out where the `labextensions` -folder is located. Then you can remove the symlink named `jupyterlab-collaborative-chat` within that folder. +folder is located. Then you can remove the symlink named `jupyterlab-collaborative-chat-extension` within that folder. ### Testing the extension -#### Server tests - -This extension is using [Pytest](https://docs.pytest.org/) for Python code testing. - -Install test dependencies (needed only once): - -```sh -pip install -e ".[test]" -# Each time you install the Python package, you need to restore the front-end extension link -jupyter labextension develop . --overwrite -``` - -To execute them, run: - -```sh -pytest -vv -r ap --cov jupyterlab_collaborative_chat -``` - #### Frontend tests This extension is using [Jest](https://jestjs.io/) for JavaScript code testing. diff --git a/packages/jupyterlab-collaborative-chat/RELEASE.md b/python/jupyterlab-collaborative-chat/RELEASE.md similarity index 100% rename from packages/jupyterlab-collaborative-chat/RELEASE.md rename to python/jupyterlab-collaborative-chat/RELEASE.md diff --git a/packages/jupyterlab-collaborative-chat/binder/environment.yml b/python/jupyterlab-collaborative-chat/binder/environment.yml similarity index 100% rename from packages/jupyterlab-collaborative-chat/binder/environment.yml rename to python/jupyterlab-collaborative-chat/binder/environment.yml diff --git a/packages/jupyterlab-collaborative-chat/binder/postBuild b/python/jupyterlab-collaborative-chat/binder/postBuild similarity index 100% rename from packages/jupyterlab-collaborative-chat/binder/postBuild rename to python/jupyterlab-collaborative-chat/binder/postBuild diff --git a/packages/jupyterlab-collaborative-chat/conftest.py b/python/jupyterlab-collaborative-chat/conftest.py similarity index 100% rename from packages/jupyterlab-collaborative-chat/conftest.py rename to python/jupyterlab-collaborative-chat/conftest.py diff --git a/packages/jupyterlab-collaborative-chat/install.json b/python/jupyterlab-collaborative-chat/install.json similarity index 100% rename from packages/jupyterlab-collaborative-chat/install.json rename to python/jupyterlab-collaborative-chat/install.json diff --git a/packages/jupyterlab-collaborative-chat/jupyter-config/server-config/jupyterlab_collaborative_chat.json b/python/jupyterlab-collaborative-chat/jupyter-config/server-config/jupyterlab_collaborative_chat.json similarity index 100% rename from packages/jupyterlab-collaborative-chat/jupyter-config/server-config/jupyterlab_collaborative_chat.json rename to python/jupyterlab-collaborative-chat/jupyter-config/server-config/jupyterlab_collaborative_chat.json diff --git a/packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/__init__.py b/python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/__init__.py similarity index 95% rename from packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/__init__.py rename to python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/__init__.py index 0418343..cd3f1cf 100644 --- a/packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/__init__.py +++ b/python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/__init__.py @@ -15,7 +15,7 @@ def _jupyter_labextension_paths(): return [{ "src": "labextension", - "dest": "jupyterlab-collaborative-chat" + "dest": "jupyterlab-collaborative-chat-extension" }] diff --git a/packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/__init__.py b/python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/__init__.py similarity index 100% rename from packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/__init__.py rename to python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/__init__.py diff --git a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/test_handlers.py b/python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/test_handlers.py similarity index 100% rename from packages/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/test_handlers.py rename to python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/tests/test_handlers.py diff --git a/packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/ychat.py b/python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/ychat.py similarity index 100% rename from packages/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/ychat.py rename to python/jupyterlab-collaborative-chat/jupyterlab_collaborative_chat/ychat.py diff --git a/python/jupyterlab-collaborative-chat/package.json b/python/jupyterlab-collaborative-chat/package.json new file mode 100644 index 0000000..22e141f --- /dev/null +++ b/python/jupyterlab-collaborative-chat/package.json @@ -0,0 +1,233 @@ +{ + "name": "jupyterlab-collaborative-chat-extension", + "version": "0.3.1", + "description": "A chat extension based on shared documents", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/jupyterlab/jupyter-chat", + "bugs": { + "url": "https://github.com/jupyterlab/jupyter-chat/issues" + }, + "license": "BSD-3-Clause", + "author": { + "name": "Jupyter Development Team", + "email": "jupyter@googlegroups.com" + }, + "files": [ + "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", + "style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}", + "src/**/*.{ts,tsx}", + "schema/*.json" + ], + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "repository": { + "type": "git", + "url": "https://github.com/jupyterlab/jupyter-chat.git" + }, + "scripts": { + "build": "jlpm build:lib && jlpm build:labextension:dev", + "build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension", + "build:labextension": "jupyter labextension build .", + "build:labextension:dev": "jupyter labextension build --development True .", + "build:lib": "tsc --sourceMap", + "build:lib:prod": "tsc", + "clean": "jlpm clean:lib", + "clean:lib": "rimraf lib tsconfig.tsbuildinfo", + "clean:lintcache": "rimraf .eslintcache .stylelintcache", + "clean:labextension": "rimraf jupyterlab_collaborative_chat/labextension jupyterlab_collaborative_chat/_version.py", + "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache", + "eslint": "jlpm eslint:check --fix", + "eslint:check": "eslint . --cache --ext .ts,.tsx", + "install:extension": "jlpm build", + "lint": "jlpm stylelint && jlpm prettier && jlpm eslint", + "lint:check": "jlpm stylelint:check && jlpm prettier:check && jlpm eslint:check", + "prettier": "jlpm prettier:base --write --list-different", + "prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"", + "prettier:check": "jlpm prettier:base --check", + "stylelint": "jlpm stylelint:check --fix", + "stylelint:check": "stylelint --cache \"style/**/*.css\"", + "watch": "run-p watch:src watch:labextension", + "watch:src": "tsc -w --sourceMap", + "watch:labextension": "jupyter labextension watch ." + }, + "dependencies": { + "@jupyter/collaboration": "^2.1.0", + "@jupyter/docprovider": "^2.1.0", + "@jupyter/ydoc": "^1.1.1", + "@jupyterlab/application": "^4.2.0", + "@jupyterlab/apputils": "^4.3.0", + "@jupyterlab/coreutils": "^6.2.0", + "@jupyterlab/docregistry": "^4.2.0", + "@jupyterlab/launcher": "^4.2.0", + "@jupyterlab/notebook": "^4.2.0", + "@jupyterlab/rendermime": "^4.2.0", + "@jupyterlab/services": "^7.2.0", + "@jupyterlab/settingregistry": "^4.2.0", + "@jupyterlab/translation": "^4.2.0", + "@jupyterlab/ui-components": "^4.2.0", + "@lumino/commands": "^2.0.0", + "@lumino/coreutils": "^2.0.0", + "@lumino/signaling": "^2.0.0", + "@lumino/widgets": "^2.0.0", + "jupyterlab-collaborative-chat": "^0.3.1", + "react": "^18.2.0", + "y-protocols": "^1.0.5", + "yjs": "^13.5.40" + }, + "devDependencies": { + "@jupyterlab/builder": "^4.2.0", + "@types/json-schema": "^7.0.11", + "@types/react": "^18.2.0", + "@types/react-addons-linked-state-mixin": "^0.14.22", + "@typescript-eslint/eslint-plugin": "^6.1.0", + "@typescript-eslint/parser": "^6.1.0", + "css-loader": "^6.7.1", + "eslint": "^8.36.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^5.0.0", + "mkdirp": "^1.0.3", + "npm-run-all": "^4.1.5", + "prettier": "^3.0.0", + "rimraf": "^5.0.1", + "source-map-loader": "^1.0.2", + "style-loader": "^3.3.1", + "stylelint": "^15.10.1", + "stylelint-config-recommended": "^13.0.0", + "stylelint-config-standard": "^34.0.0", + "stylelint-csstree-validator": "^3.0.0", + "stylelint-prettier": "^4.0.0", + "typescript": "~5.0.2", + "yjs": "^13.5.0" + }, + "sideEffects": [ + "style/*.css", + "style/index.js" + ], + "styleModule": "style/index.js", + "publishConfig": { + "access": "public" + }, + "jupyterlab": { + "discovery": { + "server": { + "managers": [ + "pip" + ], + "base": { + "name": "jupyterlab_collaborative_chat" + } + } + }, + "extension": true, + "outputDir": "jupyterlab_collaborative_chat/labextension", + "schemaDir": "schema", + "sharedPackages": { + "@jupyter/docprovider": { + "bundled": true, + "singleton": true + }, + "jupyterlab-collaborative-chat": { + "bundled": true, + "singleton": true + } + } + }, + "eslintIgnore": [ + "node_modules", + "dist", + "coverage", + "**/*.d.ts", + "tests", + "ui-tests" + ], + "eslintConfig": { + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "tsconfig.json", + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/naming-convention": [ + "error", + { + "selector": "interface", + "format": [ + "PascalCase" + ], + "custom": { + "regex": "^I[A-Z]", + "match": true + } + } + ], + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "args": "none" + } + ], + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/quotes": [ + "error", + "single", + { + "avoidEscape": true, + "allowTemplateLiterals": false + } + ], + "curly": [ + "error", + "all" + ], + "eqeqeq": "error", + "prefer-arrow-callback": "error" + } + }, + "prettier": { + "singleQuote": true, + "trailingComma": "none", + "arrowParens": "avoid", + "endOfLine": "auto", + "overrides": [ + { + "files": "package.json", + "options": { + "tabWidth": 2 + } + } + ] + }, + "stylelint": { + "extends": [ + "stylelint-config-recommended", + "stylelint-config-standard", + "stylelint-prettier/recommended" + ], + "plugins": [ + "stylelint-csstree-validator" + ], + "rules": { + "csstree/validator": true, + "property-no-vendor-prefix": null, + "selector-class-pattern": "^([a-z][A-z\\d]*)(-[A-z\\d]+)*$", + "selector-no-vendor-prefix": null, + "value-no-vendor-prefix": null + } + } +} diff --git a/packages/jupyterlab-collaborative-chat/pyproject.toml b/python/jupyterlab-collaborative-chat/pyproject.toml similarity index 97% rename from packages/jupyterlab-collaborative-chat/pyproject.toml rename to python/jupyterlab-collaborative-chat/pyproject.toml index 8a59677..3d4c0dd 100644 --- a/packages/jupyterlab-collaborative-chat/pyproject.toml +++ b/python/jupyterlab-collaborative-chat/pyproject.toml @@ -54,8 +54,8 @@ artifacts = ["jupyterlab_collaborative_chat/labextension"] exclude = [".github", "binder"] [tool.hatch.build.targets.wheel.shared-data] -"jupyterlab_collaborative_chat/labextension" = "share/jupyter/labextensions/jupyterlab-collaborative-chat" -"install.json" = "share/jupyter/labextensions/jupyterlab-collaborative-chat/install.json" +"jupyterlab_collaborative_chat/labextension" = "share/jupyter/labextensions/jupyterlab-collaborative-chat-extension" +"install.json" = "share/jupyter/labextensions/jupyterlab-collaborative-chat-extension/install.json" "jupyter-config/server-config" = "etc/jupyter/jupyter_server_config.d" [tool.hatch.build.hooks.version] diff --git a/packages/jupyterlab-collaborative-chat/schema/chat-panel.json b/python/jupyterlab-collaborative-chat/schema/chat-panel.json similarity index 100% rename from packages/jupyterlab-collaborative-chat/schema/chat-panel.json rename to python/jupyterlab-collaborative-chat/schema/chat-panel.json diff --git a/packages/jupyterlab-collaborative-chat/schema/commands.json b/python/jupyterlab-collaborative-chat/schema/commands.json similarity index 100% rename from packages/jupyterlab-collaborative-chat/schema/commands.json rename to python/jupyterlab-collaborative-chat/schema/commands.json diff --git a/packages/jupyterlab-collaborative-chat/schema/factory.json b/python/jupyterlab-collaborative-chat/schema/factory.json similarity index 100% rename from packages/jupyterlab-collaborative-chat/schema/factory.json rename to python/jupyterlab-collaborative-chat/schema/factory.json diff --git a/packages/jupyterlab-collaborative-chat/screenshot.gif b/python/jupyterlab-collaborative-chat/screenshot.gif similarity index 100% rename from packages/jupyterlab-collaborative-chat/screenshot.gif rename to python/jupyterlab-collaborative-chat/screenshot.gif diff --git a/packages/jupyterlab-collaborative-chat/setup.py b/python/jupyterlab-collaborative-chat/setup.py similarity index 100% rename from packages/jupyterlab-collaborative-chat/setup.py rename to python/jupyterlab-collaborative-chat/setup.py diff --git a/python/jupyterlab-collaborative-chat/src/index.ts b/python/jupyterlab-collaborative-chat/src/index.ts new file mode 100644 index 0000000..5d88d99 --- /dev/null +++ b/python/jupyterlab-collaborative-chat/src/index.ts @@ -0,0 +1,641 @@ +/* + * Copyright (c) Jupyter Development Team. + * Distributed under the terms of the Modified BSD License. + */ + +import { + ActiveCellManager, + AutocompletionRegistry, + IActiveCellManager, + IAutocompletionRegistry, + chatIcon, + readIcon +} from '@jupyter/chat'; +import { + ICollaborativeDrive, + SharedDocumentFactory +} from '@jupyter/docprovider'; +import { + ILayoutRestorer, + JupyterFrontEnd, + JupyterFrontEndPlugin +} from '@jupyterlab/application'; +import { + ICommandPalette, + IThemeManager, + IToolbarWidgetRegistry, + InputDialog, + WidgetTracker, + createToolbarFactory, + showErrorMessage +} from '@jupyterlab/apputils'; +import { PathExt } from '@jupyterlab/coreutils'; +import { DocumentRegistry } from '@jupyterlab/docregistry'; +import { ILauncher } from '@jupyterlab/launcher'; +import { INotebookTracker } from '@jupyterlab/notebook'; +import { IObservableList } from '@jupyterlab/observables'; +import { IRenderMimeRegistry } from '@jupyterlab/rendermime'; +import { Contents } from '@jupyterlab/services'; +import { ISettingRegistry } from '@jupyterlab/settingregistry'; +import { ITranslator, nullTranslator } from '@jupyterlab/translation'; +import { launchIcon } from '@jupyterlab/ui-components'; +import { + IActiveCellManagerToken, + chatFileType, + ChatPanel, + ChatWidgetFactory, + CollaborativeChatModel, + CollaborativeChatModelFactory, + CollaborativeChatPanel, + CommandIDs, + IChatFactory, + IChatPanel, + WidgetConfig, + YChat +} from 'jupyterlab-collaborative-chat'; + +const FACTORY = 'Chat'; + +const pluginIds = { + activeCellManager: + 'jupyterlab-collaborative-chat-extension:activeCellManager', + autocompletionRegistry: + 'jupyterlab-collaborative-chat-extension:autocompletionRegistry', + chatCommands: 'jupyterlab-collaborative-chat-extension:commands', + docFactories: 'jupyterlab-collaborative-chat-extension:factory', + chatPanel: 'jupyterlab-collaborative-chat-extension:chat-panel' +}; + +/** + * Extension providing the autocompletion registry. + */ +const autocompletionPlugin: JupyterFrontEndPlugin = { + id: pluginIds.autocompletionRegistry, + description: 'An autocompletion registry', + autoStart: true, + provides: IAutocompletionRegistry, + activate: (app: JupyterFrontEnd): IAutocompletionRegistry => { + return new AutocompletionRegistry(); + } +}; + +/** + * Extension registering the chat file type. + */ +const docFactories: JupyterFrontEndPlugin = { + id: pluginIds.docFactories, + description: 'A document factories for collaborative chat', + autoStart: true, + requires: [IRenderMimeRegistry], + optional: [ + IActiveCellManagerToken, + IAutocompletionRegistry, + ICollaborativeDrive, + ILayoutRestorer, + ISettingRegistry, + IThemeManager, + IToolbarWidgetRegistry, + ITranslator + ], + provides: IChatFactory, + activate: ( + app: JupyterFrontEnd, + rmRegistry: IRenderMimeRegistry, + activeCellManager: IActiveCellManager | null, + autocompletionRegistry: IAutocompletionRegistry, + drive: ICollaborativeDrive | null, + restorer: ILayoutRestorer | null, + settingRegistry: ISettingRegistry | null, + themeManager: IThemeManager | null, + toolbarRegistry: IToolbarWidgetRegistry | null, + translator_: ITranslator | null + ): IChatFactory => { + const translator = translator_ ?? nullTranslator; + + // Declare the toolbar factory. + let toolbarFactory: + | (( + widget: CollaborativeChatPanel + ) => + | DocumentRegistry.IToolbarItem[] + | IObservableList) + | undefined; + + /** + * Load the settings for the chat widgets. + */ + let sendWithShiftEnter = false; + let stackMessages = true; + let unreadNotifications = true; + let enableCodeToolbar = true; + function loadSetting(setting: ISettingRegistry.ISettings): void { + // Read the settings and convert to the correct type + sendWithShiftEnter = setting.get('sendWithShiftEnter') + .composite as boolean; + stackMessages = setting.get('stackMessages').composite as boolean; + unreadNotifications = setting.get('unreadNotifications') + .composite as boolean; + enableCodeToolbar = setting.get('enableCodeToolbar').composite as boolean; + widgetConfig.config = { + sendWithShiftEnter, + stackMessages, + unreadNotifications, + enableCodeToolbar + }; + } + + if (settingRegistry) { + // Create the main area widget toolbar factory. + if (toolbarRegistry) { + toolbarFactory = createToolbarFactory( + toolbarRegistry, + settingRegistry, + FACTORY, + pluginIds.docFactories, + translator + ); + } + + // Wait for the application to be restored and + // for the settings to be loaded + Promise.all([app.restored, settingRegistry.load(pluginIds.docFactories)]) + .then(([, setting]) => { + // Read the settings + loadSetting(setting); + + // Listen for the plugin setting changes + setting.changed.connect(loadSetting); + }) + .catch(reason => { + console.error( + `Something went wrong when reading the settings.\n${reason}` + ); + }); + } + + /** + * The chat config object. + */ + const widgetConfig = new WidgetConfig({ + sendWithShiftEnter, + stackMessages, + unreadNotifications, + enableCodeToolbar + }); + + // Namespace for the tracker + const namespace = 'chat'; + + // Creating the tracker for the document + const tracker = new WidgetTracker({ namespace }); + + app.docRegistry.addFileType(chatFileType); + + if (drive) { + const chatFactory: SharedDocumentFactory = () => { + return YChat.create(); + }; + drive.sharedModelFactory.registerDocumentFactory('chat', chatFactory); + } + + app.serviceManager.ready + .then(() => { + const user = app.serviceManager.user.identity; + // Creating and registering the model factory for our custom DocumentModel + const modelFactory = new CollaborativeChatModelFactory({ + user, + widgetConfig, + commands: app.commands, + activeCellManager + }); + app.docRegistry.addModelFactory(modelFactory); + }) + .catch(e => + console.error( + 'The collaborative chat model factory is not initialized', + e + ) + ); + + // Creating the widget factory to register it so the document manager knows about + // our new DocumentWidget + const widgetFactory = new ChatWidgetFactory({ + name: FACTORY, + label: 'Chat', + modelName: 'chat', + fileTypes: ['chat'], + defaultFor: ['chat'], + themeManager, + rmRegistry, + toolbarFactory, + translator, + autocompletionRegistry + }); + + // Add the widget to the tracker when it's created + widgetFactory.widgetCreated.connect((sender, widget) => { + // Notify the instance tracker if restore data needs to update. + widget.context.pathChanged.connect(() => { + tracker.save(widget); + }); + tracker.add(widget); + + // Update the 'markAsRead' command status when the unread changed. + widget.model.unreadChanged.connect(() => + app.commands.notifyCommandChanged(CommandIDs.markAsRead) + ); + }); + + // Registering the widget factory + app.docRegistry.addWidgetFactory(widgetFactory); + + // Handle state restoration. + if (restorer) { + void restorer.restore(tracker, { + command: 'docmanager:open', + args: panel => ({ path: panel.context.path, factory: FACTORY }), + name: panel => panel.context.path, + when: app.serviceManager.ready + }); + } + + return { widgetConfig, tracker }; + } +}; + +/** + * Extension providing the commands, menu and laucher. + */ +const chatCommands: JupyterFrontEndPlugin = { + id: pluginIds.chatCommands, + description: 'The commands to create or open a chat', + autoStart: true, + requires: [ICollaborativeDrive, IChatFactory], + optional: [IActiveCellManagerToken, IChatPanel, ICommandPalette, ILauncher], + activate: ( + app: JupyterFrontEnd, + drive: ICollaborativeDrive, + factory: IChatFactory, + activeCellManager: IActiveCellManager | null, + chatPanel: ChatPanel | null, + commandPalette: ICommandPalette | null, + launcher: ILauncher | null + ) => { + const { commands } = app; + const { tracker, widgetConfig } = factory; + /** + * Command to create a new chat. + * + * args: + * name - optional, the name of the chat to create. + * Open a dialog if not provided. + * inSidePanel - optional (default to false). + * Whether to open the chat in side panel or in main area. + * isPalette - optional (default to false). + * Whether the command is in commands palette or not. + */ + commands.addCommand(CommandIDs.createChat, { + label: args => (args.isPalette ? 'Create a new chat' : 'Chat'), + caption: 'Create a chat', + icon: args => (args.isPalette ? undefined : chatIcon), + execute: async args => { + const inSidePanel: boolean = (args.inSidePanel as boolean) ?? false; + let name: string | null = (args.name as string) ?? null; + let filepath = ''; + if (!name) { + name = ( + await InputDialog.getText({ + label: 'Name', + placeholder: 'untitled', + title: 'Create a new chat' + }) + ).value; + } + // no-op if the dialog has been cancelled. + // Fill the filepath if the dialog has been validated with content, + // otherwise create a new untitled chat (empty filepath). + if (name === null) { + return; + } else if (name) { + if (name.endsWith(chatFileType.extensions[0])) { + filepath = name; + } else { + filepath = `${name}${chatFileType.extensions[0]}`; + } + } + + let fileExist = true; + if (filepath) { + await drive.get(filepath, { content: false }).catch(() => { + fileExist = false; + }); + } else { + fileExist = false; + } + + // Create a new file if it does not exists + if (!fileExist) { + // Create a new untitled chat. + let model: Contents.IModel | null = await drive.newUntitled({ + type: 'file', + ext: chatFileType.extensions[0] + }); + // Rename it if a name has been provided. + if (filepath) { + model = await drive.rename(model.path, filepath); + } + + if (!model) { + showErrorMessage( + 'Error creating a chat', + 'An error occured while creating the chat' + ); + return ''; + } + filepath = model.path; + } + + if (commands.hasCommand(CommandIDs.openChat)) { + return commands.execute(CommandIDs.openChat, { + filepath, + inSidePanel + }); + } else { + commands.execute('docmanager:open', { + path: `RTC:${filepath}`, + factory: FACTORY + }); + } + } + }); + + // Add the command to the palette + if (commandPalette) { + commandPalette.addItem({ + category: 'Chat', + command: CommandIDs.createChat, + args: { isPalette: true } + }); + } + + // Add the create command to the launcher + if (launcher) { + launcher.add({ + command: CommandIDs.createChat, + category: 'Chat', + rank: 1 + }); + } + + // The command to mark the chat as read. + commands.addCommand(CommandIDs.markAsRead, { + caption: 'Mark chat as read', + icon: readIcon, + isEnabled: () => + tracker.currentWidget !== null && + tracker.currentWidget === app.shell.currentWidget && + tracker.currentWidget.model.unreadMessages.length > 0, + execute: async args => { + const widget = app.shell.currentWidget; + // Ensure widget is a CollaborativeChatPanel and is in main area + if ( + !widget || + !(widget instanceof CollaborativeChatPanel) || + !Array.from(app.shell.widgets('main')).includes(widget) + ) { + console.error( + `The command '${CommandIDs.markAsRead}' should be executed from the toolbar button only` + ); + return; + } + widget.model.unreadMessages = []; + } + }); + + // Update the 'markAsRead' command status when the current widget changes. + tracker.currentChanged.connect(() => { + commands.notifyCommandChanged(CommandIDs.markAsRead); + }); + + app.serviceManager.ready + .then(() => { + const user = app.serviceManager.user.identity; + /* + * Command to open a chat. + * + * args: + * filepath - the chat file to open. + */ + commands.addCommand(CommandIDs.openChat, { + label: 'Open a chat', + execute: async args => { + const inSidePanel: boolean = (args.inSidePanel as boolean) ?? false; + let filepath: string | null = (args.filepath as string) ?? null; + if (filepath === null) { + filepath = ( + await InputDialog.getText({ + label: 'File path', + placeholder: '/path/to/the/chat/file', + title: 'Path of the chat' + }) + ).value; + } + + if (!filepath) { + return; + } + + let fileExist = true; + await drive.get(filepath, { content: false }).catch(() => { + fileExist = false; + }); + + if (!fileExist) { + showErrorMessage( + 'Error opening chat', + `'${filepath}' is not a valid path` + ); + return; + } + + if (inSidePanel && chatPanel) { + // The chat is opened in the chat panel. + app.shell.activateById(chatPanel.id); + const model = await drive.get(filepath); + + /** + * Create a share model from the chat file + */ + const sharedModel = drive.sharedModelFactory.createNew({ + path: model.path, + format: model.format, + contentType: chatFileType.contentType, + collaborative: true + }) as YChat; + + /** + * Initialize the chat model with the share model + */ + const chat = new CollaborativeChatModel({ + user, + sharedModel, + widgetConfig, + commands: app.commands, + activeCellManager + }); + + /** + * Add a chat widget to the side panel. + */ + chatPanel.addChat( + chat, + PathExt.basename(model.name, chatFileType.extensions[0]) + ); + } else { + // The chat is opened in the main area + commands.execute('docmanager:open', { + path: `RTC:${filepath}`, + factory: FACTORY + }); + } + } + }); + + // Add the command to the palette + if (commandPalette) { + commandPalette.addItem({ + category: 'Chat', + command: CommandIDs.openChat + }); + } + }) + .catch(e => + console.error('The command to open a chat is not initialized\n', e) + ); + } +}; + +/* + * Extension providing a chat panel. + */ +const chatPanel: JupyterFrontEndPlugin = { + id: pluginIds.chatPanel, + description: 'A chat extension for Jupyter', + autoStart: true, + provides: IChatPanel, + requires: [ICollaborativeDrive, IRenderMimeRegistry], + optional: [ + IAutocompletionRegistry, + ILayoutRestorer, + INotebookTracker, + IThemeManager + ], + activate: ( + app: JupyterFrontEnd, + drive: ICollaborativeDrive, + rmRegistry: IRenderMimeRegistry, + autocompletionRegistry: IAutocompletionRegistry, + restorer: ILayoutRestorer | null, + notebookTracker: INotebookTracker, + themeManager: IThemeManager | null + ): ChatPanel => { + const { commands } = app; + + /** + * Add Chat widget to left sidebar + */ + const chatPanel = new ChatPanel({ + commands, + drive, + rmRegistry, + themeManager, + autocompletionRegistry + }); + chatPanel.id = 'JupyterCollaborationChat:sidepanel'; + chatPanel.title.icon = chatIcon; + chatPanel.title.caption = 'Jupyter Chat'; // TODO: i18n/ + + app.shell.add(chatPanel, 'left', { + rank: 2000 + }); + + if (restorer) { + restorer.add(chatPanel, 'jupyter-chat'); + } + + // Use events system to watch changes on files. + const schemaID = + 'https://events.jupyter.org/jupyter_server/contents_service/v1'; + const actions = ['create', 'delete', 'rename']; + app.serviceManager.events.stream.connect((_, emission) => { + if (emission.schema_id === schemaID) { + const action = emission.action as string; + if (actions.includes(action)) { + chatPanel.updateChatNames(); + } + } + }); + + /* + * Command to move a chat from the main area to the side panel. + * + */ + commands.addCommand(CommandIDs.moveToSide, { + label: 'Move the chat to the side panel', + caption: 'Move the chat to the side panel', + icon: launchIcon, + isEnabled: () => commands.hasCommand(CommandIDs.openChat), + execute: async () => { + const widget = app.shell.currentWidget; + // Ensure widget is a CollaborativeChatPanel and is in main area + if ( + !widget || + !(widget instanceof CollaborativeChatPanel) || + !Array.from(app.shell.widgets('main')).includes(widget) + ) { + console.error( + `The command '${CommandIDs.moveToSide}' should be executed from the toolbar button only` + ); + return; + } + // Remove potential drive prefix + const filepath = widget.context.path.split(':').pop(); + commands.execute(CommandIDs.openChat, { + filepath, + inSidePanel: true + }); + widget.dispose(); + } + }); + + return chatPanel; + } +}; + +/** + * Extension providing the active cell manager. + */ +const activeCellManager: JupyterFrontEndPlugin = { + id: pluginIds.activeCellManager, + description: 'the active cell manager plugin', + autoStart: true, + requires: [INotebookTracker], + provides: IActiveCellManagerToken, + activate: ( + app: JupyterFrontEnd, + notebookTracker: INotebookTracker + ): IActiveCellManager => { + return new ActiveCellManager({ + tracker: notebookTracker, + shell: app.shell + }); + } +}; + +export default [ + activeCellManager, + autocompletionPlugin, + chatCommands, + docFactories, + chatPanel +]; diff --git a/python/jupyterlab-collaborative-chat/style/base.css b/python/jupyterlab-collaborative-chat/style/base.css new file mode 100644 index 0000000..9618612 --- /dev/null +++ b/python/jupyterlab-collaborative-chat/style/base.css @@ -0,0 +1,12 @@ +/* + * Copyright (c) Jupyter Development Team. + * Distributed under the terms of the Modified BSD License. + */ + +/* + See the JupyterLab Developer Guide for useful CSS Patterns: + + https://jupyterlab.readthedocs.io/en/stable/developer/css.html +*/ + +@import url('~jupyterlab-collaborative-chat/style/index.css'); diff --git a/packages/jupyterlab-ws-chat/style/index.css b/python/jupyterlab-collaborative-chat/style/index.css similarity index 100% rename from packages/jupyterlab-ws-chat/style/index.css rename to python/jupyterlab-collaborative-chat/style/index.css diff --git a/packages/jupyterlab-ws-chat/style/index.js b/python/jupyterlab-collaborative-chat/style/index.js similarity index 100% rename from packages/jupyterlab-ws-chat/style/index.js rename to python/jupyterlab-collaborative-chat/style/index.js diff --git a/packages/jupyterlab-ws-chat/tsconfig.json b/python/jupyterlab-collaborative-chat/tsconfig.json similarity index 100% rename from packages/jupyterlab-ws-chat/tsconfig.json rename to python/jupyterlab-collaborative-chat/tsconfig.json diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/README.md b/python/jupyterlab-collaborative-chat/ui-tests/README.md similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/README.md rename to python/jupyterlab-collaborative-chat/ui-tests/README.md diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/jupyter_server_test_config.py b/python/jupyterlab-collaborative-chat/ui-tests/jupyter_server_test_config.py similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/jupyter_server_test_config.py rename to python/jupyterlab-collaborative-chat/ui-tests/jupyter_server_test_config.py diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/package.json b/python/jupyterlab-collaborative-chat/ui-tests/package.json similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/package.json rename to python/jupyterlab-collaborative-chat/ui-tests/package.json diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/playwright.config.js b/python/jupyterlab-collaborative-chat/ui-tests/playwright.config.js similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/playwright.config.js rename to python/jupyterlab-collaborative-chat/ui-tests/playwright.config.js diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/autocompletion.spec.ts b/python/jupyterlab-collaborative-chat/ui-tests/tests/autocompletion.spec.ts similarity index 95% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/autocompletion.spec.ts rename to python/jupyterlab-collaborative-chat/ui-tests/tests/autocompletion.spec.ts index d8769cc..5ad2061 100644 --- a/packages/jupyterlab-collaborative-chat/ui-tests/tests/autocompletion.spec.ts +++ b/python/jupyterlab-collaborative-chat/ui-tests/tests/autocompletion.spec.ts @@ -67,7 +67,7 @@ test.describe('#autocompletionRegistry', () => { async options => { // register a basic autocompletion object in registry. const registry = await window.getPlugin( - 'jupyterlab-collaborative-chat:autocompletionRegistry' + 'jupyterlab-collaborative-chat-extension:autocompletionRegistry' ); registry.removeAll(); @@ -147,7 +147,7 @@ test.describe('#autocompletionRegistry', () => { await page.evaluate( async options => { const registry = await window.getPlugin( - 'jupyterlab-collaborative-chat:autocompletionRegistry' + 'jupyterlab-collaborative-chat-extension:autocompletionRegistry' ); registry.remove('test-completion'); }, @@ -171,7 +171,7 @@ test.describe('#autocompletionRegistry', () => { await page.evaluate( async options => { const registry = await window.getPlugin( - 'jupyterlab-collaborative-chat:autocompletionRegistry' + 'jupyterlab-collaborative-chat-extension:autocompletionRegistry' ); const autocompletion = { opener: options.newOpener, @@ -211,7 +211,7 @@ test.describe('#autocompletionRegistry', () => { const added = await page.evaluate( async options => { const registry = await window.getPlugin( - 'jupyterlab-collaborative-chat:autocompletionRegistry' + 'jupyterlab-collaborative-chat-extension:autocompletionRegistry' ); const autocompletion = { opener: options.newOpener, @@ -246,7 +246,7 @@ test.describe('#autocompletionRegistry', () => { await page.evaluate( async options => { const registry = await window.getPlugin( - 'jupyterlab-collaborative-chat:autocompletionRegistry' + 'jupyterlab-collaborative-chat-extension:autocompletionRegistry' ); const autocompletion = { opener: options.newOpener, @@ -277,7 +277,7 @@ test('should use properties from autocompletion object', async ({ page }) => { await page.evaluate( async options => { const registry = await window.getPlugin( - 'jupyterlab-collaborative-chat:autocompletionRegistry' + 'jupyterlab-collaborative-chat-extension:autocompletionRegistry' ); registry.removeAll(); const autocompletion = { @@ -312,7 +312,7 @@ test('single autocompletion should be the default', async ({ page }) => { await page.evaluate( async options => { const registry = await window.getPlugin( - 'jupyterlab-collaborative-chat:autocompletionRegistry' + 'jupyterlab-collaborative-chat-extension:autocompletionRegistry' ); registry.removeAll(); const autocompletion = { diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/code-toolbar.spec.ts b/python/jupyterlab-collaborative-chat/ui-tests/tests/code-toolbar.spec.ts similarity index 99% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/code-toolbar.spec.ts rename to python/jupyterlab-collaborative-chat/ui-tests/tests/code-toolbar.spec.ts index 90f381d..182acaa 100644 --- a/packages/jupyterlab-collaborative-chat/ui-tests/tests/code-toolbar.spec.ts +++ b/python/jupyterlab-collaborative-chat/ui-tests/tests/code-toolbar.spec.ts @@ -16,7 +16,7 @@ test.use({ mockUser: USER, mockSettings: { ...galata.DEFAULT_SETTINGS, - 'jupyterlab-collaborative-chat:factory': { + 'jupyterlab-collaborative-chat-extension:factory': { sendWithShiftEnter: true } } diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts similarity index 99% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts index 9ac9e7a..629fdcc 100644 --- a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts +++ b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts @@ -225,7 +225,7 @@ test.describe('#settings', () => { const settings = await openSettings(page, true); await expect( settings.locator( - '.jp-PluginList-entry[data-id="jupyterlab-collaborative-chat:factory"]' + '.jp-PluginList-entry[data-id="jupyterlab-collaborative-chat-extension:factory"]' ) ).toBeVisible(); }); diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/chat-icon-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/chat-icon-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/chat-icon-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/chat-icon-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/launcher-tile-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/launcher-tile-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/launcher-tile-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/launcher-tile-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/menu-new-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/menu-new-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/menu-new-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/menu-new-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/moveToMain-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/moveToMain-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/moveToMain-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/moveToMain-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/moveToSide-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/moveToSide-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/moveToSide-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/moveToSide-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-bottom-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-bottom-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-bottom-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-bottom-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-bottom-unread-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-bottom-unread-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-bottom-unread-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-bottom-unread-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-top-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-top-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-top-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/navigation-top-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/not-stacked-messages-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/not-stacked-messages-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/not-stacked-messages-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/not-stacked-messages-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/stacked-messages-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/stacked-messages-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/stacked-messages-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/stacked-messages-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/tab-with-unread-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/tab-with-unread-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/tab-with-unread-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/tab-with-unread-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/tab-without-unread-linux.png b/python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/tab-without-unread-linux.png similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/tab-without-unread-linux.png rename to python/jupyterlab-collaborative-chat/ui-tests/tests/jupyterlab_collaborative_chat.spec.ts-snapshots/tab-without-unread-linux.png diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/tests/test-utils.ts b/python/jupyterlab-collaborative-chat/ui-tests/tests/test-utils.ts similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/tests/test-utils.ts rename to python/jupyterlab-collaborative-chat/ui-tests/tests/test-utils.ts diff --git a/packages/jupyterlab-collaborative-chat/ui-tests/yarn.lock b/python/jupyterlab-collaborative-chat/ui-tests/yarn.lock similarity index 100% rename from packages/jupyterlab-collaborative-chat/ui-tests/yarn.lock rename to python/jupyterlab-collaborative-chat/ui-tests/yarn.lock diff --git a/packages/jupyterlab-ws-chat/LICENSE b/python/jupyterlab-ws-chat/LICENSE similarity index 100% rename from packages/jupyterlab-ws-chat/LICENSE rename to python/jupyterlab-ws-chat/LICENSE diff --git a/packages/jupyterlab-ws-chat/README.md b/python/jupyterlab-ws-chat/README.md similarity index 51% rename from packages/jupyterlab-ws-chat/README.md rename to python/jupyterlab-ws-chat/README.md index 4d93cbe..fce2ffc 100644 --- a/packages/jupyterlab-ws-chat/README.md +++ b/python/jupyterlab-ws-chat/README.md @@ -2,10 +2,10 @@ [![Github Actions Status](https://github.com/jupyterlab/jupyter-chat/workflows/Build/badge.svg)](https://github.com/jupyterlab/jupyter-chat/actions/workflows/build.yml) -A chat extension for Jupyterlab +A chat extension for Jupyterlab, based on websocket for exchanging messages. This package is composed of a Python package named `jupyterlab_ws_chat` -for the server side and a NPM package named `jupyterlab-ws-chat` +for the server side and a NPM package named `jupyterlab-ws-chat-extension` ![screenshot](screenshot.png 'WS chat extension') @@ -41,38 +41,47 @@ The `jlpm` command is JupyterLab's pinned version of ```bash # Clone the repo to your local environment -# Change directory to the jupyter-chat/jupyterlab-ws-chat directory +# Change directory to the python/jupyterlab-ws-chat directory # Install package in development mode pip install -e ".[test]" +# Link your development version of the extension with JupyterLab +jupyter labextension develop . --overwrite +# Server extension must be manually installed in develop mode +jupyter server extension enable jupyterlab_ws_chat # Rebuild Typescript source after making changes jlpm build ``` -By default, the `jlpm build` command generates the source maps for this package to make it easier to debug using the browser dev tools. - -### Development uninstall +You can watch the source directory and run JupyterLab at the same time in different terminals to watch for changes in the extension's source and automatically rebuild the extension. ```bash -pip uninstall jupyterlab_ws_chat +# Watch the source directory in one terminal, automatically rebuilding when needed +jlpm watch +# Run JupyterLab in another terminal +jupyter lab ``` -### Testing the package +With the watch command running, every saved change will immediately be built locally and available in your running JupyterLab. Refresh JupyterLab to load the change in your browser (you may need to wait several seconds for the extension to be rebuilt). -#### Server tests +By default, the `jlpm build` command generates the source maps for this extension to make it easier to debug using the browser dev tools. To also generate source maps for the JupyterLab core extensions, you can run the following command: -This extension is using [Pytest](https://docs.pytest.org/) for Python code testing. +```bash +jupyter lab build --minimize=False +``` -Install test dependencies (needed only once): +### Development uninstall -```sh -pip install -e ".[test]" +```bash +# Server extension must be manually disabled in develop mode +jupyter server extension disable jupyterlab_ws_chat +pip uninstall jupyterlab_ws_chat ``` -To execute them, run: +In development mode, you will also need to remove the symlink created by `jupyter labextension develop` +command. To find its location, you can run `jupyter labextension list` to figure out where the `labextensions` +folder is located. Then you can remove the symlink named `jupyterlab-ws-chat-extension` within that folder. -```sh -pytest -vv -r ap --cov jupyterlab_ws_chat -``` +### Testing the package #### Frontend tests diff --git a/packages/jupyterlab-ws-chat/RELEASE.md b/python/jupyterlab-ws-chat/RELEASE.md similarity index 100% rename from packages/jupyterlab-ws-chat/RELEASE.md rename to python/jupyterlab-ws-chat/RELEASE.md diff --git a/packages/jupyterlab-ws-chat/babel.config.js b/python/jupyterlab-ws-chat/babel.config.js similarity index 100% rename from packages/jupyterlab-ws-chat/babel.config.js rename to python/jupyterlab-ws-chat/babel.config.js diff --git a/packages/jupyterlab-ws-chat/install.json b/python/jupyterlab-ws-chat/install.json similarity index 100% rename from packages/jupyterlab-ws-chat/install.json rename to python/jupyterlab-ws-chat/install.json diff --git a/packages/jupyterlab-ws-chat/jupyter-config/server-config/jupyter_chat.json b/python/jupyterlab-ws-chat/jupyter-config/server-config/jupyterlab_ws_chat.json similarity index 100% rename from packages/jupyterlab-ws-chat/jupyter-config/server-config/jupyter_chat.json rename to python/jupyterlab-ws-chat/jupyter-config/server-config/jupyterlab_ws_chat.json diff --git a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/__init__.py b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/__init__.py similarity index 90% rename from packages/jupyterlab-ws-chat/jupyterlab_ws_chat/__init__.py rename to python/jupyterlab-ws-chat/jupyterlab_ws_chat/__init__.py index 24fd7ce..138d184 100644 --- a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/__init__.py +++ b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/__init__.py @@ -14,7 +14,7 @@ from .extension import ChatExtension def _jupyter_labextension_paths(): - return [{"src": "labextension", "dest": "jupyterlab-ws-chat"}] + return [{"src": "labextension", "dest": "jupyterlab-ws-chat-extension"}] def _jupyter_server_extension_points(): diff --git a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/config/config_schema.json b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/config/config_schema.json similarity index 100% rename from packages/jupyterlab-ws-chat/jupyterlab_ws_chat/config/config_schema.json rename to python/jupyterlab-ws-chat/jupyterlab_ws_chat/config/config_schema.json diff --git a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/config_manager.py b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/config_manager.py similarity index 100% rename from packages/jupyterlab-ws-chat/jupyterlab_ws_chat/config_manager.py rename to python/jupyterlab-ws-chat/jupyterlab_ws_chat/config_manager.py diff --git a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/extension.py b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/extension.py similarity index 100% rename from packages/jupyterlab-ws-chat/jupyterlab_ws_chat/extension.py rename to python/jupyterlab-ws-chat/jupyterlab_ws_chat/extension.py diff --git a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/handlers.py b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/handlers.py similarity index 100% rename from packages/jupyterlab-ws-chat/jupyterlab_ws_chat/handlers.py rename to python/jupyterlab-ws-chat/jupyterlab_ws_chat/handlers.py diff --git a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/models.py b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/models.py similarity index 100% rename from packages/jupyterlab-ws-chat/jupyterlab_ws_chat/models.py rename to python/jupyterlab-ws-chat/jupyterlab_ws_chat/models.py diff --git a/packages/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/__init__.py b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/__init__.py similarity index 100% rename from packages/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/__init__.py rename to python/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/__init__.py diff --git a/python/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/test_handlers.py b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/test_handlers.py new file mode 100644 index 0000000..902af76 --- /dev/null +++ b/python/jupyterlab-ws-chat/jupyterlab_ws_chat/tests/test_handlers.py @@ -0,0 +1,4 @@ +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + +### TODO #### diff --git a/packages/jupyterlab-ws-chat/package.json b/python/jupyterlab-ws-chat/package.json similarity index 95% rename from packages/jupyterlab-ws-chat/package.json rename to python/jupyterlab-ws-chat/package.json index 8a1527f..2945403 100644 --- a/packages/jupyterlab-ws-chat/package.json +++ b/python/jupyterlab-ws-chat/package.json @@ -1,5 +1,5 @@ { - "name": "jupyterlab-ws-chat", + "name": "jupyterlab-ws-chat-extension", "version": "0.3.1", "description": "A chat extension for Jupyterlab", "keywords": [ @@ -40,7 +40,7 @@ "clean:lib": "rimraf lib tsconfig.tsbuildinfo", "clean:lintcache": "rimraf .eslintcache .stylelintcache", "clean:labextension": "rimraf jupyterlab_ws_chat/labextension jupyterlab_ws_chat/_version.py", - "clean:all": "jlpm clean:lib && clean:labextension && jlpm clean:lintcache", + "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache", "eslint": "jlpm eslint:check --fix", "eslint:check": "eslint . --cache --ext .ts,.tsx", "install:extension": "jlpm build", @@ -51,7 +51,9 @@ "prettier:check": "jlpm prettier:base --check", "stylelint": "jlpm stylelint:check --fix", "stylelint:check": "stylelint --cache \"style/**/*.css\"", - "watch:src": "tsc -w --sourceMap" + "watch": "run-p watch:src watch:labextension", + "watch:src": "tsc -w --sourceMap", + "watch:labextension": "jupyter labextension watch ." }, "dependencies": { "@jupyter/chat": "^0.3.1", @@ -65,7 +67,6 @@ }, "devDependencies": { "@jupyterlab/builder": "^4.2.0", - "@jupyterlab/testutils": "^4.2.0", "@types/json-schema": "^7.0.11", "@types/react": "^18.2.0", "@types/react-addons-linked-state-mixin": "^0.14.22", @@ -119,7 +120,6 @@ "coverage", "**/*.d.ts", "tests", - "**/__tests__", "ui-tests" ], "eslintConfig": { diff --git a/packages/jupyterlab-ws-chat/pyproject.toml b/python/jupyterlab-ws-chat/pyproject.toml similarity index 96% rename from packages/jupyterlab-ws-chat/pyproject.toml rename to python/jupyterlab-ws-chat/pyproject.toml index e099bbc..8fab436 100644 --- a/packages/jupyterlab-ws-chat/pyproject.toml +++ b/python/jupyterlab-ws-chat/pyproject.toml @@ -54,10 +54,9 @@ artifacts = ["jupyterlab_ws_chat/labextension"] exclude = [".github", "binder"] [tool.hatch.build.targets.wheel.shared-data] -"jupyterlab_ws_chat/labextension" = "share/jupyter/labextensions/jupyterlab-ws-chat" -"install.json" = "share/jupyter/labextensions/jupyterlab-ws-chat/install.json" +"jupyterlab_ws_chat/labextension" = "share/jupyter/labextensions/jupyterlab-ws-chat-extension" +"install.json" = "share/jupyter/labextensions/jupyterlab-ws-chat-extension/install.json" "jupyter-config/server-config" = "etc/jupyter/jupyter_server_config.d" -"jupyter-config/nb-config" = "etc/jupyter/jupyter_notebook_config.d" [tool.hatch.build.hooks.version] path = "jupyterlab_ws_chat/_version.py" diff --git a/packages/jupyterlab-ws-chat/schema/chat.json b/python/jupyterlab-ws-chat/schema/chat.json similarity index 100% rename from packages/jupyterlab-ws-chat/schema/chat.json rename to python/jupyterlab-ws-chat/schema/chat.json diff --git a/packages/jupyterlab-ws-chat/screenshot.png b/python/jupyterlab-ws-chat/screenshot.png similarity index 100% rename from packages/jupyterlab-ws-chat/screenshot.png rename to python/jupyterlab-ws-chat/screenshot.png diff --git a/packages/jupyterlab-ws-chat/setup.py b/python/jupyterlab-ws-chat/setup.py similarity index 100% rename from packages/jupyterlab-ws-chat/setup.py rename to python/jupyterlab-ws-chat/setup.py diff --git a/packages/jupyterlab-ws-chat/src/handlers/handler.ts b/python/jupyterlab-ws-chat/src/handlers/handler.ts similarity index 100% rename from packages/jupyterlab-ws-chat/src/handlers/handler.ts rename to python/jupyterlab-ws-chat/src/handlers/handler.ts diff --git a/packages/jupyterlab-ws-chat/src/handlers/websocket-handler.ts b/python/jupyterlab-ws-chat/src/handlers/websocket-handler.ts similarity index 100% rename from packages/jupyterlab-ws-chat/src/handlers/websocket-handler.ts rename to python/jupyterlab-ws-chat/src/handlers/websocket-handler.ts diff --git a/packages/jupyterlab-ws-chat/src/index.ts b/python/jupyterlab-ws-chat/src/index.ts similarity index 97% rename from packages/jupyterlab-ws-chat/src/index.ts rename to python/jupyterlab-ws-chat/src/index.ts index 1e0526a..6716b01 100644 --- a/packages/jupyterlab-ws-chat/src/index.ts +++ b/python/jupyterlab-ws-chat/src/index.ts @@ -23,8 +23,8 @@ import { ISettingRegistry } from '@jupyterlab/settingregistry'; import { WebSocketHandler } from './handlers/websocket-handler'; const pluginIds = { - autocompletionRegistry: 'jupyterlab-ws-chat:autocompletionRegistry', - chat: 'jupyterlab-ws-chat:chat' + autocompletionRegistry: 'jupyterlab-ws-chat-extension:autocompletionRegistry', + chat: 'jupyterlab-ws-chat-extension:chat' }; /** diff --git a/packages/jupyterlab-ws-chat/style/base.css b/python/jupyterlab-ws-chat/style/base.css similarity index 100% rename from packages/jupyterlab-ws-chat/style/base.css rename to python/jupyterlab-ws-chat/style/base.css diff --git a/packages/jupyterlab-ws-chat/style/icons/chat.svg b/python/jupyterlab-ws-chat/style/icons/chat.svg similarity index 100% rename from packages/jupyterlab-ws-chat/style/icons/chat.svg rename to python/jupyterlab-ws-chat/style/icons/chat.svg diff --git a/python/jupyterlab-ws-chat/style/index.css b/python/jupyterlab-ws-chat/style/index.css new file mode 100644 index 0000000..c236c5e --- /dev/null +++ b/python/jupyterlab-ws-chat/style/index.css @@ -0,0 +1,6 @@ +/* + * Copyright (c) Jupyter Development Team. + * Distributed under the terms of the Modified BSD License. + */ + +@import url('base.css'); diff --git a/python/jupyterlab-ws-chat/style/index.js b/python/jupyterlab-ws-chat/style/index.js new file mode 100644 index 0000000..71b038b --- /dev/null +++ b/python/jupyterlab-ws-chat/style/index.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) Jupyter Development Team. + * Distributed under the terms of the Modified BSD License. + */ + +import './base.css'; diff --git a/python/jupyterlab-ws-chat/tsconfig.json b/python/jupyterlab-ws-chat/tsconfig.json new file mode 100644 index 0000000..92d6e92 --- /dev/null +++ b/python/jupyterlab-ws-chat/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + }, + "include": ["src/**/*"] +} diff --git a/packages/jupyterlab-ws-chat/tsconfig.test.json b/python/jupyterlab-ws-chat/tsconfig.test.json similarity index 100% rename from packages/jupyterlab-ws-chat/tsconfig.test.json rename to python/jupyterlab-ws-chat/tsconfig.test.json diff --git a/packages/jupyterlab-ws-chat/ui-tests/README.md b/python/jupyterlab-ws-chat/ui-tests/README.md similarity index 100% rename from packages/jupyterlab-ws-chat/ui-tests/README.md rename to python/jupyterlab-ws-chat/ui-tests/README.md diff --git a/packages/jupyterlab-ws-chat/ui-tests/jupyter_server_test_config.py b/python/jupyterlab-ws-chat/ui-tests/jupyter_server_test_config.py similarity index 100% rename from packages/jupyterlab-ws-chat/ui-tests/jupyter_server_test_config.py rename to python/jupyterlab-ws-chat/ui-tests/jupyter_server_test_config.py diff --git a/packages/jupyterlab-ws-chat/ui-tests/package.json b/python/jupyterlab-ws-chat/ui-tests/package.json similarity index 100% rename from packages/jupyterlab-ws-chat/ui-tests/package.json rename to python/jupyterlab-ws-chat/ui-tests/package.json diff --git a/packages/jupyterlab-ws-chat/ui-tests/playwright.config.js b/python/jupyterlab-ws-chat/ui-tests/playwright.config.js similarity index 100% rename from packages/jupyterlab-ws-chat/ui-tests/playwright.config.js rename to python/jupyterlab-ws-chat/ui-tests/playwright.config.js diff --git a/packages/jupyterlab-ws-chat/ui-tests/tests/jupyterlab_chat_extension.spec.ts b/python/jupyterlab-ws-chat/ui-tests/tests/jupyterlab_chat_extension.spec.ts similarity index 100% rename from packages/jupyterlab-ws-chat/ui-tests/tests/jupyterlab_chat_extension.spec.ts rename to python/jupyterlab-ws-chat/ui-tests/tests/jupyterlab_chat_extension.spec.ts diff --git a/packages/jupyterlab-ws-chat/ui-tests/yarn.lock b/python/jupyterlab-ws-chat/ui-tests/yarn.lock similarity index 100% rename from packages/jupyterlab-ws-chat/ui-tests/yarn.lock rename to python/jupyterlab-ws-chat/ui-tests/yarn.lock diff --git a/scripts/install.sh b/scripts/install.sh index ffd0949..c6e48d2 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -11,12 +11,12 @@ jlpm install if [ -z "${EXTENSION}" ]; then jlpm build # install the collaborative chat extension - pip install -e packages/jupyterlab-collaborative-chat[test] + pip install -e python/jupyterlab-collaborative-chat[test] # install websocket chat extension - pip install -e packages/jupyterlab-ws-chat[test] + pip install -e python/jupyterlab-ws-chat[test] else PACKAGE="jupyterlab-${EXTENSION}-chat" jlpm build:${EXTENSION} - pip install -e packages/${PACKAGE}[test] + pip install -e python/${PACKAGE}[test] fi diff --git a/yarn.lock b/yarn.lock index 42c8db3..cf1c525 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,14 +25,44 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.24.8": +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.25.2, @babel/compat-data@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/compat-data@npm:7.25.4" + checksum: b12a91d27c3731a4b0bdc9312a50b1911f41f7f728aaf0d4b32486e2257fd2cb2d3ea1a295e98449600c48f2c7883a3196ca77cda1cef7d97a10c2e83d037974 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.24.8": version: 7.24.9 resolution: "@babel/compat-data@npm:7.24.9" checksum: 3590be0f7028bca0565a83f66752c0f0283b818e9e1bb7fc12912822768e379a6ff84c59d77dc64ba62c140b8500a3828d95c0ce013cd62d254a179bae38709b languageName: node linkType: hard -"@babel/core@npm:^7.10.2, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9": +"@babel/core@npm:^7.10.2": + version: 7.25.2 + resolution: "@babel/core@npm:7.25.2" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.25.0 + "@babel/helper-compilation-targets": ^7.25.2 + "@babel/helper-module-transforms": ^7.25.2 + "@babel/helpers": ^7.25.0 + "@babel/parser": ^7.25.0 + "@babel/template": ^7.25.0 + "@babel/traverse": ^7.25.2 + "@babel/types": ^7.25.2 + convert-source-map: ^2.0.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.3 + semver: ^6.3.1 + checksum: 9a1ef604a7eb62195f70f9370cec45472a08114e3934e3eaaedee8fd754edf0730e62347c7b4b5e67d743ce57b5bb8cf3b92459482ca94d06e06246ef021390a + languageName: node + linkType: hard + +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9": version: 7.24.9 resolution: "@babel/core@npm:7.24.9" dependencies: @@ -67,6 +97,18 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.25.0, @babel/generator@npm:^7.25.6": + version: 7.25.6 + resolution: "@babel/generator@npm:7.25.6" + dependencies: + "@babel/types": ^7.25.6 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + jsesc: ^2.5.1 + checksum: b55975cd664f5602304d868bb34f4ee3bed6f5c7ce8132cd92ff27a46a53a119def28a182d91992e86f75db904f63094a81247703c4dc96e4db0c03fd04bcd68 + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-annotate-as-pure@npm:7.24.7" @@ -86,7 +128,20 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7, @babel/helper-compilation-targets@npm:^7.24.8": +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7, @babel/helper-compilation-targets@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-compilation-targets@npm:7.25.2" + dependencies: + "@babel/compat-data": ^7.25.2 + "@babel/helper-validator-option": ^7.24.8 + browserslist: ^4.23.1 + lru-cache: ^5.1.1 + semver: ^6.3.1 + checksum: aed33c5496cb9db4b5e2d44e26bf8bc474074cc7f7bb5ebe1d4a20fdeb362cb3ba9e1596ca18c7484bcd6e5c3a155ab975e420d520c0ae60df81f9de04d0fd16 + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.24.8": version: 7.24.8 resolution: "@babel/helper-compilation-targets@npm:7.24.8" dependencies: @@ -99,39 +154,37 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.24.7": - version: 7.24.8 - resolution: "@babel/helper-create-class-features-plugin@npm:7.24.8" +"@babel/helper-create-class-features-plugin@npm:^7.24.7, @babel/helper-create-class-features-plugin@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/helper-create-class-features-plugin@npm:7.25.4" dependencies: "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-function-name": ^7.24.7 "@babel/helper-member-expression-to-functions": ^7.24.8 "@babel/helper-optimise-call-expression": ^7.24.7 - "@babel/helper-replace-supers": ^7.24.7 + "@babel/helper-replace-supers": ^7.25.0 "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 - "@babel/helper-split-export-declaration": ^7.24.7 + "@babel/traverse": ^7.25.4 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: b4707e2c4a2cb504d7656168d887bf653db6fbe8ece4502e28e5798f2ec624dc606f2d6bc4820d31b4dc1b80f7d83d98db83516dda321a76c075e5f531abed0b + checksum: 4544ebda4516eb25efdebd47ca024bd7bdb1eb6e7cc3ad89688c8ef8e889734c2f4411ed78981899c641394f013f246f2af63d92a0e9270f6c453309b4cb89ba languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.24.7" +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.24.7, @babel/helper-create-regexp-features-plugin@npm:^7.25.0, @babel/helper-create-regexp-features-plugin@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.25.2" dependencies: "@babel/helper-annotate-as-pure": ^7.24.7 regexpu-core: ^5.3.1 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: 17c59fa222af50f643946eca940ce1d474ff2da1f4afed2312687ab9d708ebbb8c9372754ddbdf44b6e21ead88b8fc144644f3a7b63ccb886de002458cef3974 + checksum: df55fdc6a1f3090dd37d91347df52d9322d52affa239543808dc142f8fe35e6787e67d8612337668198fac85826fafa9e6772e6c28b7d249ec94e6fafae5da6e languageName: node linkType: hard -"@babel/helper-define-polyfill-provider@npm:^0.6.1, @babel/helper-define-polyfill-provider@npm:^0.6.2": +"@babel/helper-define-polyfill-provider@npm:^0.6.2": version: 0.6.2 resolution: "@babel/helper-define-polyfill-provider@npm:0.6.2" dependencies: @@ -174,7 +227,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.24.7, @babel/helper-member-expression-to-functions@npm:^7.24.8": +"@babel/helper-member-expression-to-functions@npm:^7.24.8": version: 7.24.8 resolution: "@babel/helper-member-expression-to-functions@npm:7.24.8" dependencies: @@ -194,7 +247,21 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.24.9": +"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.25.0, @babel/helper-module-transforms@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-module-transforms@npm:7.25.2" + dependencies: + "@babel/helper-module-imports": ^7.24.7 + "@babel/helper-simple-access": ^7.24.7 + "@babel/helper-validator-identifier": ^7.24.7 + "@babel/traverse": ^7.25.2 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 282d4e3308df6746289e46e9c39a0870819630af5f84d632559171e4fae6045684d771a65f62df3d569e88ccf81dc2def78b8338a449ae3a94bb421aa14fc367 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.24.9": version: 7.24.9 resolution: "@babel/helper-module-transforms@npm:7.24.9" dependencies: @@ -225,29 +292,29 @@ __metadata: languageName: node linkType: hard -"@babel/helper-remap-async-to-generator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-remap-async-to-generator@npm:7.24.7" +"@babel/helper-remap-async-to-generator@npm:^7.24.7, @babel/helper-remap-async-to-generator@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-remap-async-to-generator@npm:7.25.0" dependencies: "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-wrap-function": ^7.24.7 + "@babel/helper-wrap-function": ^7.25.0 + "@babel/traverse": ^7.25.0 peerDependencies: "@babel/core": ^7.0.0 - checksum: bab7be178f875350f22a2cb9248f67fe3a8a8128db77a25607096ca7599fd972bc7049fb11ed9e95b45a3f1dd1fac3846a3279f9cbac16f337ecb0e6ca76e1fc + checksum: 47f3065e43fe9d6128ddb4291ffb9cf031935379265fd13de972b5f241943121f7583efb69cd2e1ecf39e3d0f76f047547d56c3fcc2c853b326fad5465da0bd7 languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-replace-supers@npm:7.24.7" +"@babel/helper-replace-supers@npm:^7.24.7, @babel/helper-replace-supers@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-replace-supers@npm:7.25.0" dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-member-expression-to-functions": ^7.24.7 + "@babel/helper-member-expression-to-functions": ^7.24.8 "@babel/helper-optimise-call-expression": ^7.24.7 + "@babel/traverse": ^7.25.0 peerDependencies: "@babel/core": ^7.0.0 - checksum: 2bf0d113355c60d86a04e930812d36f5691f26c82d4ec1739e5ec0a4c982c9113dad3167f7c74f888a96328bd5e696372232406d8200e5979e6e0dc2af5e7c76 + checksum: f669fc2487c22d40b808f94b9c3ee41129484d5ef0ba689bdd70f216ff91e10b6b021d2f8cd37e7bdd700235a2a6ae6622526344f064528190383bf661ac65f8 languageName: node linkType: hard @@ -301,15 +368,14 @@ __metadata: languageName: node linkType: hard -"@babel/helper-wrap-function@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-wrap-function@npm:7.24.7" +"@babel/helper-wrap-function@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-wrap-function@npm:7.25.0" dependencies: - "@babel/helper-function-name": ^7.24.7 - "@babel/template": ^7.24.7 - "@babel/traverse": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: 085bf130ed08670336e3976f5841ae44e3e10001131632e22ef234659341978d2fd37e65785f59b6cb1745481347fc3bce84b33a685cacb0a297afbe1d2b03af + "@babel/template": ^7.25.0 + "@babel/traverse": ^7.25.0 + "@babel/types": ^7.25.0 + checksum: 0095b4741704066d1687f9bbd5370bb88c733919e4275e49615f70c180208148ff5f24ab58d186ce92f8f5d28eab034ec6617e9264590cc4744c75302857629c languageName: node linkType: hard @@ -323,6 +389,16 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.25.0": + version: 7.25.6 + resolution: "@babel/helpers@npm:7.25.6" + dependencies: + "@babel/template": ^7.25.0 + "@babel/types": ^7.25.6 + checksum: 5a548999db82049a5f7ac6de57576b4ed0d386ce07d058151698836ed411eae6230db12535487caeebb68a2ffc964491e8aead62364a5132ab0ae20e8b68e19f + languageName: node + linkType: hard + "@babel/highlight@npm:^7.24.7": version: 7.24.7 resolution: "@babel/highlight@npm:7.24.7" @@ -344,26 +420,48 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.24.7" +"@babel/parser@npm:^7.25.0, @babel/parser@npm:^7.25.6": + version: 7.25.6 + resolution: "@babel/parser@npm:7.25.6" dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/types": ^7.25.6 + bin: + parser: ./bin/babel-parser.js + checksum: 85b237ded09ee43cc984493c35f3b1ff8a83e8dbbb8026b8132e692db6567acc5a1659ec928e4baa25499ddd840d7dae9dee3062be7108fe23ec5f94a8066b1e + languageName: node + linkType: hard + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.3": + version: 7.25.3 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.25.3" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.3 peerDependencies: "@babel/core": ^7.0.0 - checksum: 68d315642b53af143aa17a71eb976cf431b51339aee584e29514a462b81c998636dd54219c2713b5f13e1df89eaf130dfab59683f9116825608708c81696b96c + checksum: d3dba60f360defe70eb43e35a1b17ea9dd4a99e734249e15be3d5c288019644f96f88d7ff51990118fda0845b4ad50f6d869e0382232b1d8b054d113d4eea7e2 languageName: node linkType: hard -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.24.7" +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.25.0" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: fd56d1e6435f2c008ca9050ea906ff7eedcbec43f532f2bf2e7e905d8bf75bf5e4295ea9593f060394e2c8e45737266ccbf718050bad2dd7be4e7613c60d1b5b + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 peerDependencies: "@babel/core": ^7.0.0 - checksum: 7eb4e7ce5e3d6db4b0fdbdfaaa301c2e58f38a7ee39d5a4259a1fda61a612e83d3e4bc90fc36fb0345baf57e1e1a071e0caffeb80218623ad163f2fdc2e53a54 + checksum: 13ed301b108d85867d64226bbc4032b07dd1a23aab68e9e32452c4fe3930f2198bb65bdae9c262c4104bd5e45647bc1830d25d43d356ee9a137edd8d5fab8350 languageName: node linkType: hard @@ -380,15 +478,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.24.7" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.25.0" dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.0 peerDependencies: "@babel/core": ^7.0.0 - checksum: 8324d458db57060590942c7c2e9603880d07718ccb6450ec935105b8bd3c4393c4b8ada88e178c232258d91f33ffdcf2b1043d54e07a86989e50667ee100a32e + checksum: c8d08b8d6cc71451ad2a50cf7db72ab5b41c1e5e2e4d56cf6837a25a61270abd682c6b8881ab025f11a552d2024b3780519bb051459ebb71c27aed13d9917663 languageName: node linkType: hard @@ -468,24 +566,24 @@ __metadata: linkType: hard "@babel/plugin-syntax-import-assertions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.24.7" + version: 7.25.6 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.25.6" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.8 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c4d67be4eb1d4637e361477dbe01f5b392b037d17c1f861cfa0faa120030e137aab90a9237931b8040fd31d1e5d159e11866fa1165f78beef7a3be876a391a17 + checksum: b3b251ace9f184c2d6369cde686ff01581050cb0796f2ff00ff4021f31cf86270b347df09579f2c0996e999e37e1dddafacec42ed1ef6aae21a265aff947e792 languageName: node linkType: hard "@babel/plugin-syntax-import-attributes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.7" + version: 7.25.6 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.25.6" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.8 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 590dbb5d1a15264f74670b427b8d18527672c3d6c91d7bae7e65f80fd810edbc83d90e68065088644cbad3f2457ed265a54a9956fb789fcb9a5b521822b3a275 + checksum: 3b0928e73e42346e8a65760a3ff853c87ad693cdf11bb335a23e895e0b5b1f0601118521b3aff2a6946488a580a63afb6a5b5686153a7678b4dff0e4e4604dd7 languageName: node linkType: hard @@ -644,17 +742,17 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.24.7" +"@babel/plugin-transform-async-generator-functions@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.4" dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-remap-async-to-generator": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-remap-async-to-generator": ^7.25.0 "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/traverse": ^7.25.4 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 112e3b18f9c496ebc01209fc27f0b41a3669c479c7bc44f7249383172b432ebaae1e523caa7c6ecbd2d0d7adcb7e5769fe2798f8cb01c08cd57232d1bb6d8ad4 + checksum: 4235444735a1946f8766fe56564a8134c2c36c73e6cf83b3f2ed5624ebc84ff5979506a6a5b39acdb23aa09d442a6af471710ed408ccce533a2c4d2990b9df6a languageName: node linkType: hard @@ -682,26 +780,26 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-block-scoping@npm:7.24.7" +"@babel/plugin-transform-block-scoping@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-block-scoping@npm:7.25.0" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.8 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 039206155533600f079f3a455f85888dd7d4970ff7ffa85ef44760f4f5acb9f19c9d848cc1fec1b9bdbc0dfec9e8a080b90d0ab66ad2bdc7138b5ca4ba96e61c + checksum: b1a8f932f69ad2a47ae3e02b4cedd2a876bfc2ac9cf72a503fd706cdc87272646fe9eed81e068c0fc639647033de29f7fa0c21cddd1da0026f83dbaac97316a8 languageName: node linkType: hard -"@babel/plugin-transform-class-properties@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-class-properties@npm:7.24.7" +"@babel/plugin-transform-class-properties@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-class-properties@npm:7.25.4" dependencies: - "@babel/helper-create-class-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-class-features-plugin": ^7.25.4 + "@babel/helper-plugin-utils": ^7.24.8 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 1348d7ce74da38ba52ea85b3b4289a6a86913748569ef92ef0cff30702a9eb849e5eaf59f1c6f3517059aa68115fb3067e389735dccacca39add4e2b0c67e291 + checksum: b73f7d968639c6c2dfc13f4c5a8fe45cefd260f0faa7890ae12e65d41211072544ff5e128c8b61a86887b29ffd3df8422dbdfbf61648488e71d4bb599c41f4a5 languageName: node linkType: hard @@ -718,21 +816,19 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/plugin-transform-classes@npm:7.24.8" +"@babel/plugin-transform-classes@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-classes@npm:7.25.4" dependencies: "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-compilation-targets": ^7.24.8 - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-function-name": ^7.24.7 + "@babel/helper-compilation-targets": ^7.25.2 "@babel/helper-plugin-utils": ^7.24.8 - "@babel/helper-replace-supers": ^7.24.7 - "@babel/helper-split-export-declaration": ^7.24.7 + "@babel/helper-replace-supers": ^7.25.0 + "@babel/traverse": ^7.25.4 globals: ^11.1.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9c0f547d67e255b37055461df9c1a578c29bf59c7055bd5b40b07b92e5448af3ca8d853d50056125b7dae9bfe3a4cf1559d61b9ccbc3d2578dd43f15386f12fe + checksum: 0bf20e46eeb691bd60cee5d1b01950fc37accec88018ecace25099f7c8d8509c1ac54d11b8caf9f2157c6945969520642a3bc421159c1a14e80224dc9a7611de languageName: node linkType: hard @@ -782,6 +878,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.25.0" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.25.0 + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 608d6b0e77341189508880fd1a9f605a38d0803dd6f678ea3920ab181b17b377f6d5221ae8cf0104c7a044d30d4ddb0366bd064447695671d78457a656bb264f + languageName: node + linkType: hard + "@babel/plugin-transform-dynamic-import@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-dynamic-import@npm:7.24.7" @@ -830,16 +938,16 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-function-name@npm:7.24.7" +"@babel/plugin-transform-function-name@npm:^7.25.1": + version: 7.25.1 + resolution: "@babel/plugin-transform-function-name@npm:7.25.1" dependencies: - "@babel/helper-compilation-targets": ^7.24.7 - "@babel/helper-function-name": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-compilation-targets": ^7.24.8 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8eb1a67894a124910b5a67630bed4307757504381f39f0fb5cf82afc7ae8647dbc03b256d13865b73a749b9071b68e9fb8a28cef2369917b4299ebb93fd66146 + checksum: 743f3ea03bbc5a90944849d5a880b6bd9243dddbde581a46952da76e53a0b74c1e2424133fe8129d7a152c1f8c872bcd27e0b6728d7caadabd1afa7bb892e1e0 languageName: node linkType: hard @@ -855,14 +963,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-literals@npm:7.24.7" +"@babel/plugin-transform-literals@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/plugin-transform-literals@npm:7.25.2" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.8 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3c075cc093a3dd9e294b8b7d6656e65f889e7ca2179ca27978dcd65b4dc4885ebbfb327408d7d8f483c55547deed00ba840956196f3ac8a3c3d2308a330a8c23 + checksum: 70c9bb40e377a306bd8f500899fb72127e527517914466e95dc6bb53fa7a0f51479db244a54a771b5780fc1eab488fedd706669bf11097b81a23c81ab7423eb1 languageName: node linkType: hard @@ -914,17 +1022,17 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.24.7" +"@babel/plugin-transform-modules-systemjs@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.25.0" dependencies: - "@babel/helper-hoist-variables": ^7.24.7 - "@babel/helper-module-transforms": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-module-transforms": ^7.25.0 + "@babel/helper-plugin-utils": ^7.24.8 "@babel/helper-validator-identifier": ^7.24.7 + "@babel/traverse": ^7.25.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8af7a9db2929991d82cfdf41fb175dee344274d39b39122f8c35f24b5d682f98368e3d8f5130401298bd21412df21d416a7d8b33b59c334fae3d3c762118b1d8 + checksum: fe673bec08564e491847324bb80a1e6edfb229f5c37e58a094d51e95306e7b098e1d130fc43e992d22debd93b9beac74441ffc3f6ea5d78f6b2535896efa0728 languageName: node linkType: hard @@ -1049,15 +1157,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-private-methods@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-private-methods@npm:7.24.7" +"@babel/plugin-transform-private-methods@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-private-methods@npm:7.25.4" dependencies: - "@babel/helper-create-class-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-class-features-plugin": ^7.25.4 + "@babel/helper-plugin-utils": ^7.24.8 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c151548e34909be2adcceb224d8fdd70bafa393bc1559a600906f3f647317575bf40db670470934a360e90ee8084ef36dffa34ec25d387d414afd841e74cf3fe + checksum: cb1dabfc03e2977990263d65bc8f43a9037dffbb5d9a5f825c00d05447ff68015099408c1531d9dd88f18a41a90f5062dc48f3a1d52b415d2d2ee4827dedff09 languageName: node linkType: hard @@ -1200,30 +1308,31 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-unicode-sets-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.24.7" +"@babel/plugin-transform-unicode-sets-regex@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.25.4" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-regexp-features-plugin": ^7.25.2 + "@babel/helper-plugin-utils": ^7.24.8 peerDependencies: "@babel/core": ^7.0.0 - checksum: 08a2844914f33dacd2ce1ab021ce8c1cc35dc6568521a746d8bf29c21571ee5be78787b454231c4bb3526cbbe280f1893223c82726cec5df2be5dae0a3b51837 + checksum: 6d1a7e9fdde4ffc9a81c0e3f261b96a9a0dfe65da282ec96fe63b36c597a7389feac638f1df2a8a4f8c9128337bba8e984f934e9f19077930f33abf1926759ea languageName: node linkType: hard "@babel/preset-env@npm:^7.10.2": - version: 7.24.8 - resolution: "@babel/preset-env@npm:7.24.8" + version: 7.25.4 + resolution: "@babel/preset-env@npm:7.25.4" dependencies: - "@babel/compat-data": ^7.24.8 - "@babel/helper-compilation-targets": ^7.24.8 + "@babel/compat-data": ^7.25.4 + "@babel/helper-compilation-targets": ^7.25.2 "@babel/helper-plugin-utils": ^7.24.8 "@babel/helper-validator-option": ^7.24.8 - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.24.7 - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.24.7 + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.25.3 + "@babel/plugin-bugfix-safari-class-field-initializer-scope": ^7.25.0 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.25.0 "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.24.7 - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.24.7 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.25.0 "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 "@babel/plugin-syntax-async-generators": ^7.8.4 "@babel/plugin-syntax-class-properties": ^7.12.13 @@ -1244,29 +1353,30 @@ __metadata: "@babel/plugin-syntax-top-level-await": ^7.14.5 "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 "@babel/plugin-transform-arrow-functions": ^7.24.7 - "@babel/plugin-transform-async-generator-functions": ^7.24.7 + "@babel/plugin-transform-async-generator-functions": ^7.25.4 "@babel/plugin-transform-async-to-generator": ^7.24.7 "@babel/plugin-transform-block-scoped-functions": ^7.24.7 - "@babel/plugin-transform-block-scoping": ^7.24.7 - "@babel/plugin-transform-class-properties": ^7.24.7 + "@babel/plugin-transform-block-scoping": ^7.25.0 + "@babel/plugin-transform-class-properties": ^7.25.4 "@babel/plugin-transform-class-static-block": ^7.24.7 - "@babel/plugin-transform-classes": ^7.24.8 + "@babel/plugin-transform-classes": ^7.25.4 "@babel/plugin-transform-computed-properties": ^7.24.7 "@babel/plugin-transform-destructuring": ^7.24.8 "@babel/plugin-transform-dotall-regex": ^7.24.7 "@babel/plugin-transform-duplicate-keys": ^7.24.7 + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ^7.25.0 "@babel/plugin-transform-dynamic-import": ^7.24.7 "@babel/plugin-transform-exponentiation-operator": ^7.24.7 "@babel/plugin-transform-export-namespace-from": ^7.24.7 "@babel/plugin-transform-for-of": ^7.24.7 - "@babel/plugin-transform-function-name": ^7.24.7 + "@babel/plugin-transform-function-name": ^7.25.1 "@babel/plugin-transform-json-strings": ^7.24.7 - "@babel/plugin-transform-literals": ^7.24.7 + "@babel/plugin-transform-literals": ^7.25.2 "@babel/plugin-transform-logical-assignment-operators": ^7.24.7 "@babel/plugin-transform-member-expression-literals": ^7.24.7 "@babel/plugin-transform-modules-amd": ^7.24.7 "@babel/plugin-transform-modules-commonjs": ^7.24.8 - "@babel/plugin-transform-modules-systemjs": ^7.24.7 + "@babel/plugin-transform-modules-systemjs": ^7.25.0 "@babel/plugin-transform-modules-umd": ^7.24.7 "@babel/plugin-transform-named-capturing-groups-regex": ^7.24.7 "@babel/plugin-transform-new-target": ^7.24.7 @@ -1277,7 +1387,7 @@ __metadata: "@babel/plugin-transform-optional-catch-binding": ^7.24.7 "@babel/plugin-transform-optional-chaining": ^7.24.8 "@babel/plugin-transform-parameters": ^7.24.7 - "@babel/plugin-transform-private-methods": ^7.24.7 + "@babel/plugin-transform-private-methods": ^7.25.4 "@babel/plugin-transform-private-property-in-object": ^7.24.7 "@babel/plugin-transform-property-literals": ^7.24.7 "@babel/plugin-transform-regenerator": ^7.24.7 @@ -1290,16 +1400,16 @@ __metadata: "@babel/plugin-transform-unicode-escapes": ^7.24.7 "@babel/plugin-transform-unicode-property-regex": ^7.24.7 "@babel/plugin-transform-unicode-regex": ^7.24.7 - "@babel/plugin-transform-unicode-sets-regex": ^7.24.7 + "@babel/plugin-transform-unicode-sets-regex": ^7.25.4 "@babel/preset-modules": 0.1.6-no-external-plugins babel-plugin-polyfill-corejs2: ^0.4.10 - babel-plugin-polyfill-corejs3: ^0.10.4 + babel-plugin-polyfill-corejs3: ^0.10.6 babel-plugin-polyfill-regenerator: ^0.6.1 core-js-compat: ^3.37.1 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: efea0039dbb089c9cc0b792b9ac0eef949699584b4c622e2abea062b44b1a0fbcda6ad25e2263ae36a69586889b4a22439a1096aa8152b366e3fedd921ae66ac + checksum: 752be43f0b78a2eefe5007076aed3d21b505e1c09d134b61e7de8838f1bbb1e7af81023d39adb14b6eae23727fb5a9fd23f8115a44df043319be22319be17913 languageName: node linkType: hard @@ -1323,7 +1433,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": version: 7.24.8 resolution: "@babel/runtime@npm:7.24.8" dependencies: @@ -1332,6 +1442,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.8.4": + version: 7.25.6 + resolution: "@babel/runtime@npm:7.25.6" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: ee1a69d3ac7802803f5ee6a96e652b78b8addc28c6a38c725a4ad7d61a059d9e6cb9f6550ed2f63cce67a1bd82e0b1ef66a1079d895be6bfb536a5cfbd9ccc32 + languageName: node + linkType: hard + "@babel/template@npm:^7.24.7, @babel/template@npm:^7.3.3": version: 7.24.7 resolution: "@babel/template@npm:7.24.7" @@ -1343,6 +1462,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/template@npm:7.25.0" + dependencies: + "@babel/code-frame": ^7.24.7 + "@babel/parser": ^7.25.0 + "@babel/types": ^7.25.0 + checksum: 3f2db568718756d0daf2a16927b78f00c425046b654cd30b450006f2e84bdccaf0cbe6dc04994aa1f5f6a4398da2f11f3640a4d3ee31722e43539c4c919c817b + languageName: node + linkType: hard + "@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8": version: 7.24.8 resolution: "@babel/traverse@npm:7.24.8" @@ -1361,7 +1491,22 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": +"@babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.1, @babel/traverse@npm:^7.25.2, @babel/traverse@npm:^7.25.3, @babel/traverse@npm:^7.25.4": + version: 7.25.6 + resolution: "@babel/traverse@npm:7.25.6" + dependencies: + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.25.6 + "@babel/parser": ^7.25.6 + "@babel/template": ^7.25.0 + "@babel/types": ^7.25.6 + debug: ^4.3.1 + globals: ^11.1.0 + checksum: 11ee47269aa4356f2d6633a05b9af73405b5ed72c09378daf644289b686ef852035a6ac9aa410f601991993c6bbf72006795b5478283b78eb1ca77874ada7737 + languageName: node + linkType: hard + +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": version: 7.24.9 resolution: "@babel/types@npm:7.24.9" dependencies: @@ -1372,6 +1517,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.25.0, @babel/types@npm:^7.25.2, @babel/types@npm:^7.25.6, @babel/types@npm:^7.4.4": + version: 7.25.6 + resolution: "@babel/types@npm:7.25.6" + dependencies: + "@babel/helper-string-parser": ^7.24.8 + "@babel/helper-validator-identifier": ^7.24.7 + to-fast-properties: ^2.0.0 + checksum: 9b2f84ff3f874ad05b0b9bf06862c56f478b65781801f82296b4cc01bee39e79c20a7c0a06959fed0ee582c8267e1cb21638318655c5e070b0287242a844d1c9 + languageName: node + linkType: hard + "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -2285,6 +2441,7 @@ __metadata: "@jupyterlab/apputils": ^4.3.0 "@jupyterlab/notebook": ^4.2.0 "@jupyterlab/rendermime": ^4.2.0 + "@jupyterlab/testing": ^4.2.0 "@jupyterlab/ui-components": ^4.2.0 "@lumino/commands": ^2.0.0 "@lumino/disposable": ^2.0.0 @@ -2409,7 +2566,7 @@ __metadata: languageName: node linkType: hard -"@jupyterlab/application@npm:^4.2.0, @jupyterlab/application@npm:^4.2.3": +"@jupyterlab/application@npm:^4.2.0": version: 4.2.3 resolution: "@jupyterlab/application@npm:4.2.3" dependencies: @@ -2637,6 +2794,20 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/coreutils@npm:^6.2.5": + version: 6.2.5 + resolution: "@jupyterlab/coreutils@npm:6.2.5" + dependencies: + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/signaling": ^2.1.2 + minimist: ~1.2.0 + path-browserify: ^1.0.0 + url-parse: ~1.5.4 + checksum: 3b6a10b117ee82a437b6535801fe012bb5af7769a850be95c8ffa666ee2d6f7c29041ba546c9cfca0ab32b65f91c661570541f4f785f48af9022d08407c0a3e5 + languageName: node + linkType: hard + "@jupyterlab/docmanager@npm:^4.2.3": version: 4.2.3 resolution: "@jupyterlab/docmanager@npm:4.2.3" @@ -2785,7 +2956,7 @@ __metadata: languageName: node linkType: hard -"@jupyterlab/notebook@npm:^4.2.0, @jupyterlab/notebook@npm:^4.2.3": +"@jupyterlab/notebook@npm:^4.2.0": version: 4.2.3 resolution: "@jupyterlab/notebook@npm:4.2.3" dependencies: @@ -2955,13 +3126,13 @@ __metadata: languageName: node linkType: hard -"@jupyterlab/testing@npm:^4.2.3": - version: 4.2.3 - resolution: "@jupyterlab/testing@npm:4.2.3" +"@jupyterlab/testing@npm:^4.2.0": + version: 4.2.5 + resolution: "@jupyterlab/testing@npm:4.2.5" dependencies: "@babel/core": ^7.10.2 "@babel/preset-env": ^7.10.2 - "@jupyterlab/coreutils": ^6.2.3 + "@jupyterlab/coreutils": ^6.2.5 "@lumino/coreutils": ^2.1.2 "@lumino/signaling": ^2.1.2 deepmerge: ^4.2.2 @@ -2974,20 +3145,7 @@ __metadata: ts-jest: ^29.1.0 peerDependencies: typescript: ">=4.3" - checksum: 06e2a6b2c81c6eee6fc8808ab05a7200089f388fd43d29407be1bb48493d93722331eaf03cb3f875c58df65d6d81f05cf0a8c4b89f2bd34683da8a10e1ebcf56 - languageName: node - linkType: hard - -"@jupyterlab/testutils@npm:^4.2.0": - version: 4.2.3 - resolution: "@jupyterlab/testutils@npm:4.2.3" - dependencies: - "@jupyterlab/application": ^4.2.3 - "@jupyterlab/apputils": ^4.3.3 - "@jupyterlab/notebook": ^4.2.3 - "@jupyterlab/rendermime": ^4.2.3 - "@jupyterlab/testing": ^4.2.3 - checksum: bada58b53e21c965a81b83105c1a1335688ca8d47118ba197b170de79c7b9f82c2c680ef6c17b01e0a307d5cfa3f10ef365f4c4b4025d99d139b1cc7d7a6997b + checksum: 504a8bd43a73cab399289e7e0d3e9e92887f2353394e7d1c11bf40e54eadb4d14d441cff9c9fae021d8a000216fd5d80d18d268362e23815cdd2ff29dd239ae3 languageName: node linkType: hard @@ -5055,11 +5213,11 @@ __metadata: linkType: hard "acorn-walk@npm:^8.0.2": - version: 8.3.3 - resolution: "acorn-walk@npm:8.3.3" + version: 8.3.4 + resolution: "acorn-walk@npm:8.3.4" dependencies: acorn: ^8.11.0 - checksum: 0f09d351fc30b69b2b9982bf33dc30f3d35a34e030e5f1ed3c49fc4e3814a192bf3101e4c30912a0595410f5e91bb70ddba011ea73398b3ecbfe41c7334c6dd0 + checksum: 4ff03f42323e7cf90f1683e08606b0f460e1e6ac263d2730e3df91c7665b6f64e696db6ea27ee4bed18c2599569be61f28a8399fa170c611161a348c402ca19c languageName: node linkType: hard @@ -5468,15 +5626,15 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs3@npm:^0.10.4": - version: 0.10.4 - resolution: "babel-plugin-polyfill-corejs3@npm:0.10.4" +"babel-plugin-polyfill-corejs3@npm:^0.10.6": + version: 0.10.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.10.6" dependencies: - "@babel/helper-define-polyfill-provider": ^0.6.1 - core-js-compat: ^3.36.1 + "@babel/helper-define-polyfill-provider": ^0.6.2 + core-js-compat: ^3.38.0 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: b96a54495f7cc8b3797251c8c15f5ed015edddc3110fc122f6b32c94bec33af1e8bc56fa99091808f500bde0cccaaa266889cdc5935d9e6e9cf09898214f02dd + checksum: f762f29f7acca576897c63149c850f0a72babd3fb9ea436a2e36f0c339161c4b912a77828541d8188ce8a91e50965c6687120cf36071eabb1b7aa92f279e2164 languageName: node linkType: hard @@ -5611,7 +5769,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.21.10, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1": +"browserslist@npm:^4.21.10, browserslist@npm:^4.23.1": version: 4.23.2 resolution: "browserslist@npm:4.23.2" dependencies: @@ -5625,7 +5783,21 @@ __metadata: languageName: node linkType: hard -"bs-logger@npm:0.x": +"browserslist@npm:^4.23.3": + version: 4.23.3 + resolution: "browserslist@npm:4.23.3" + dependencies: + caniuse-lite: ^1.0.30001646 + electron-to-chromium: ^1.5.4 + node-releases: ^2.0.18 + update-browserslist-db: ^1.1.0 + bin: + browserslist: cli.js + checksum: 7906064f9970aeb941310b2fcb8b4ace4a1b50aa657c986677c6f1553a8cabcc94ee9c5922f715baffbedaa0e6cf0831b6fed7b059dde6873a4bfadcbe069c7e + languageName: node + linkType: hard + +"bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" dependencies: @@ -5813,6 +5985,13 @@ __metadata: languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001646": + version: 1.0.30001660 + resolution: "caniuse-lite@npm:1.0.30001660" + checksum: 8b2c5de2f5facd31980426afbba68238270984acfe8c1ae925b8b6480448eea2fae292f815674617e9170c730c8a238d7cc0db919f184dc0e3cd9bec18f5e5ad + languageName: node + linkType: hard + "chalk@npm:4.1.0": version: 4.1.0 resolution: "chalk@npm:4.1.0" @@ -6294,12 +6473,12 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.36.1, core-js-compat@npm:^3.37.1": - version: 3.37.1 - resolution: "core-js-compat@npm:3.37.1" +"core-js-compat@npm:^3.37.1, core-js-compat@npm:^3.38.0": + version: 3.38.1 + resolution: "core-js-compat@npm:3.38.1" dependencies: - browserslist: ^4.23.0 - checksum: 5e7430329358bced08c30950512d2081aea0a5652b4c5892cbb3c4a6db05b0d3893a191a955162a07fdb5f4fe74e61b6429fdb503f54e062336d76e43c9555d9 + browserslist: ^4.23.3 + checksum: a0a5673bcd59f588f0cd0b59cdacd4712b82909738a87406d334dd412eb3d273ae72b275bdd8e8fef63fca9ef12b42ed651be139c7c44c8a1acb423c8906992e languageName: node linkType: hard @@ -6872,7 +7051,7 @@ __metadata: languageName: node linkType: hard -"ejs@npm:^3.0.0, ejs@npm:^3.1.7": +"ejs@npm:^3.1.10, ejs@npm:^3.1.7": version: 3.1.10 resolution: "ejs@npm:3.1.10" dependencies: @@ -6890,6 +7069,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.5.4": + version: 1.5.19 + resolution: "electron-to-chromium@npm:1.5.19" + checksum: 459b47ab828cbeb2d09767c93cd181bdccbda008e1d7fc92d078d72ecf4cac3107d2deb424016a63aadc484765ec98c84f339546b0a627892d24eb286f9f0adb + languageName: node + linkType: hard + "emittery@npm:^0.13.1": version: 0.13.1 resolution: "emittery@npm:0.13.1" @@ -9824,7 +10010,58 @@ __metadata: languageName: unknown linkType: soft -"jupyterlab-collaborative-chat@workspace:packages/jupyterlab-collaborative-chat": +"jupyterlab-collaborative-chat-extension@workspace:python/jupyterlab-collaborative-chat": + version: 0.0.0-use.local + resolution: "jupyterlab-collaborative-chat-extension@workspace:python/jupyterlab-collaborative-chat" + dependencies: + "@jupyter/collaboration": ^2.1.0 + "@jupyter/docprovider": ^2.1.0 + "@jupyter/ydoc": ^1.1.1 + "@jupyterlab/application": ^4.2.0 + "@jupyterlab/apputils": ^4.3.0 + "@jupyterlab/builder": ^4.2.0 + "@jupyterlab/coreutils": ^6.2.0 + "@jupyterlab/docregistry": ^4.2.0 + "@jupyterlab/launcher": ^4.2.0 + "@jupyterlab/notebook": ^4.2.0 + "@jupyterlab/rendermime": ^4.2.0 + "@jupyterlab/services": ^7.2.0 + "@jupyterlab/settingregistry": ^4.2.0 + "@jupyterlab/translation": ^4.2.0 + "@jupyterlab/ui-components": ^4.2.0 + "@lumino/commands": ^2.0.0 + "@lumino/coreutils": ^2.0.0 + "@lumino/signaling": ^2.0.0 + "@lumino/widgets": ^2.0.0 + "@types/json-schema": ^7.0.11 + "@types/react": ^18.2.0 + "@types/react-addons-linked-state-mixin": ^0.14.22 + "@typescript-eslint/eslint-plugin": ^6.1.0 + "@typescript-eslint/parser": ^6.1.0 + css-loader: ^6.7.1 + eslint: ^8.36.0 + eslint-config-prettier: ^8.8.0 + eslint-plugin-prettier: ^5.0.0 + jupyterlab-collaborative-chat: ^0.3.1 + mkdirp: ^1.0.3 + npm-run-all: ^4.1.5 + prettier: ^3.0.0 + react: ^18.2.0 + rimraf: ^5.0.1 + source-map-loader: ^1.0.2 + style-loader: ^3.3.1 + stylelint: ^15.10.1 + stylelint-config-recommended: ^13.0.0 + stylelint-config-standard: ^34.0.0 + stylelint-csstree-validator: ^3.0.0 + stylelint-prettier: ^4.0.0 + typescript: ~5.0.2 + y-protocols: ^1.0.5 + yjs: ^13.5.0 + languageName: unknown + linkType: soft + +"jupyterlab-collaborative-chat@^0.3.1, jupyterlab-collaborative-chat@workspace:packages/jupyterlab-collaborative-chat": version: 0.0.0-use.local resolution: "jupyterlab-collaborative-chat@workspace:packages/jupyterlab-collaborative-chat" dependencies: @@ -9834,7 +10071,6 @@ __metadata: "@jupyter/ydoc": ^1.1.1 "@jupyterlab/application": ^4.2.0 "@jupyterlab/apputils": ^4.3.0 - "@jupyterlab/builder": ^4.2.0 "@jupyterlab/coreutils": ^6.2.0 "@jupyterlab/docregistry": ^4.2.0 "@jupyterlab/launcher": ^4.2.0 @@ -9842,7 +10078,7 @@ __metadata: "@jupyterlab/rendermime": ^4.2.0 "@jupyterlab/services": ^7.2.0 "@jupyterlab/settingregistry": ^4.2.0 - "@jupyterlab/testutils": ^4.2.0 + "@jupyterlab/testing": ^4.2.0 "@jupyterlab/translation": ^4.2.0 "@jupyterlab/ui-components": ^4.2.0 "@lumino/commands": ^2.0.0 @@ -9878,9 +10114,9 @@ __metadata: languageName: unknown linkType: soft -"jupyterlab-ws-chat@workspace:packages/jupyterlab-ws-chat": +"jupyterlab-ws-chat-extension@workspace:python/jupyterlab-ws-chat": version: 0.0.0-use.local - resolution: "jupyterlab-ws-chat@workspace:packages/jupyterlab-ws-chat" + resolution: "jupyterlab-ws-chat-extension@workspace:python/jupyterlab-ws-chat" dependencies: "@jupyter/chat": ^0.3.1 "@jupyterlab/apputils": ^4.3.0 @@ -9890,7 +10126,6 @@ __metadata: "@jupyterlab/rendermime": ^4.2.0 "@jupyterlab/services": ^7.2.0 "@jupyterlab/settingregistry": ^4.2.0 - "@jupyterlab/testutils": ^4.2.0 "@lumino/coreutils": ^2.0.0 "@types/json-schema": ^7.0.11 "@types/react": ^18.2.0 @@ -10334,7 +10569,7 @@ __metadata: languageName: node linkType: hard -"lodash.memoize@npm:4.x": +"lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" checksum: 9ff3942feeccffa4f1fafa88d32f0d24fdc62fd15ded5a74a5f950ff5f0c6f61916157246744c620173dddf38d37095a92327d5fd3861e2063e736a5c207d089 @@ -10457,7 +10692,7 @@ __metadata: languageName: node linkType: hard -"make-error@npm:1.x": +"make-error@npm:^1.3.6": version: 1.3.6 resolution: "make-error@npm:1.3.6" checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 @@ -11123,6 +11358,13 @@ __metadata: languageName: node linkType: hard +"node-releases@npm:^2.0.18": + version: 2.0.18 + resolution: "node-releases@npm:2.0.18" + checksum: ef55a3d853e1269a6d6279b7692cd6ff3e40bc74947945101138745bfdc9a5edabfe72cb19a31a8e45752e1910c4c65c77d931866af6357f242b172b7283f5b3 + languageName: node + linkType: hard + "nopt@npm:^6.0.0": version: 6.0.0 resolution: "nopt@npm:6.0.0" @@ -12988,6 +13230,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.3": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8 + languageName: node + linkType: hard + "serialize-javascript@npm:^6.0.1": version: 6.0.2 resolution: "serialize-javascript@npm:6.0.2" @@ -14026,18 +14277,18 @@ __metadata: linkType: hard "ts-jest@npm:^29.1.0": - version: 29.2.2 - resolution: "ts-jest@npm:29.2.2" + version: 29.2.5 + resolution: "ts-jest@npm:29.2.5" dependencies: - bs-logger: 0.x - ejs: ^3.0.0 - fast-json-stable-stringify: 2.x + bs-logger: ^0.2.6 + ejs: ^3.1.10 + fast-json-stable-stringify: ^2.1.0 jest-util: ^29.0.0 json5: ^2.2.3 - lodash.memoize: 4.x - make-error: 1.x - semver: ^7.5.3 - yargs-parser: ^21.0.1 + lodash.memoize: ^4.1.2 + make-error: ^1.3.6 + semver: ^7.6.3 + yargs-parser: ^21.1.1 peerDependencies: "@babel/core": ">=7.0.0-beta.0 <8" "@jest/transform": ^29.0.0 @@ -14058,7 +14309,7 @@ __metadata: optional: true bin: ts-jest: cli.js - checksum: e8e20167ecab9d164215691ea60e946774519fd602809599d1f2abf8321a767310e9ee2cf377a346a3d6de7b8a8ac619180bb0ab06f3813e51f82973f5a94b82 + checksum: d60d1e1d80936f6002b1bb27f7e062408bc733141b9d666565503f023c340a3196d506c836a4316c5793af81a5f910ab49bb9c13f66e2dc66de4e0f03851dbca languageName: node linkType: hard @@ -15173,7 +15424,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:21.1.1, yargs-parser@npm:^21.0.1, yargs-parser@npm:^21.1.1": +"yargs-parser@npm:21.1.1, yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c