diff --git a/package-lock.json b/package-lock.json index 297fd33b..92345259 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,12 @@ ], "dependencies": { "@lancedb/lancedb": "^0.5.2", + "@tiptap/extension-mention": "^2.5.9", + "@tiptap/extension-placeholder": "^2.5.9", + "@tiptap/pm": "^2.5.9", + "@tiptap/react": "^2.5.9", + "@tiptap/starter-kit": "^2.5.9", + "@tiptap/suggestion": "^2.5.9", "@types/react": "^18.2.46", "@vscode/codicons": "^0.0.35", "@vscode/vsce": "^2.31.1", @@ -43,6 +49,7 @@ "remark-gfm": "^4.0.0", "stream-http": "^3.2.0", "string_score": "^0.1.22", + "tippy.js": "^6.3.7", "toxe": "^1.1.0", "uuid": "^9.0.1" }, @@ -2365,6 +2372,15 @@ "node": ">=14" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -2419,6 +2435,11 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@remirror/core-constants": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-2.0.2.tgz", + "integrity": "sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==" + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2463,6 +2484,391 @@ "tslib": "^2.4.0" } }, + "node_modules/@tiptap/core": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.5.9.tgz", + "integrity": "sha512-PPUR+0tbr+wX2G8RG4FEps4qhbnAPEeXK1FUtirLXSRh8vm+TDgafu3sms7wBc4fAyw9zTO/KNNZ90GBe04guA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-blockquote": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.5.9.tgz", + "integrity": "sha512-LhGyigmd/v1OjYPeoVK8UvFHbH6ffh175ZuNvseZY4PsBd7kZhrSUiuMG8xYdNX8FxamsxAzr2YpsYnOzu3W7A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.5.9.tgz", + "integrity": "sha512-XUJdzFb31t0+bwiRquJf0btBpqOB3axQNHTKM9XADuL4S+Z6OBPj0I5rYINeElw/Q7muvdWrHWHh/ovNJA1/5A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-bubble-menu": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.5.9.tgz", + "integrity": "sha512-NddZ8Qn5dgPPa1W4yk0jdhF4tDBh0FwzBpbnDu2Xz/0TUHrA36ugB2CvR5xS1we4zUKckgpVqOqgdelrmqqFVg==", + "dependencies": { + "tippy.js": "^6.3.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-bullet-list": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.5.9.tgz", + "integrity": "sha512-hJTv1x4omFgaID4LMRT5tOZb/VKmi8Kc6jsf4JNq4Grxd2sANmr9qpmKtBZvviK+XD5PpTXHvL+1c8C1SQtuHQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-code": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.5.9.tgz", + "integrity": "sha512-Q1PL3DUXiEe5eYUwOug1haRjSaB0doAKwx7KFVI+kSGbDwCV6BdkKAeYf3us/O2pMP9D0im8RWX4dbSnatgwBA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-code-block": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.5.9.tgz", + "integrity": "sha512-+MUwp0VFFv2aFiZ/qN6q10vfIc6VhLoFFpfuETX10eIRks0Xuj2nGiqCDj7ca0/M44bRg2VvW8+tg/ZEHFNl9g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-document": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.5.9.tgz", + "integrity": "sha512-VdNZYDyCzC3W430UdeRXR9IZzPeODSbi5Xz/JEdV93THVp8AC9CrZR7/qjqdBTgbTB54VP8Yr6bKfCoIAF0BeQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-dropcursor": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.5.9.tgz", + "integrity": "sha512-nEOb37UryG6bsU9JAs/HojE6Jg43LupNTAMISbnuB1CPAeAqNsFMwORd9eEPkyEwnQT7MkhsMOSJM44GoPGIFA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-floating-menu": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.5.9.tgz", + "integrity": "sha512-MWJIQQT6e5MgqHny8neeH2Dx926nVPF7sv4p84nX4E0dnkRbEYUP8mCsWYhSUvxxIif6e+yY+4654f2Q9qTx1w==", + "dependencies": { + "tippy.js": "^6.3.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-gapcursor": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.5.9.tgz", + "integrity": "sha512-yW7V2ebezsa7mWEDWCg4A1ZGsmSV5bEHKse9wzHCDkb7TutSVhLZxGo72U6hNN9PnAksv+FJQk03NuZNYvNyRQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-hard-break": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.5.9.tgz", + "integrity": "sha512-8hQ63SgZRG4BqHOeSfeaowG2eMr2beced018pOGbpHbE3XSYoISkMVuFz4Z8UEVR3W9dTbKo4wxNufSTducocQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.5.9.tgz", + "integrity": "sha512-HHowAlGUbFn1qvmY02ydM7qiPPMTGhAJn2A46enDRjNHW5UoqeMfkMpTEYaioOexyguRFSfDT3gpK68IHkQORQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-history": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.5.9.tgz", + "integrity": "sha512-hGPtJgoZSwnVVqi/xipC2ET/9X2G2UI/Y+M3IYV1ZlM0tCYsv4spNi3uXlZqnXRwYcBXLk5u6e/dmsy5QFbL8g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.5.9.tgz", + "integrity": "sha512-/ES5NdxCndBmZAgIXSpCJH8YzENcpxR0S8w34coSWyv+iW0Sq7rW/mksQw8ZIVsj8a7ntpoY5OoRFpSlqcvyGw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.5.9.tgz", + "integrity": "sha512-Bw+P139L4cy+B56zpUiRjP8BZSaAUl3JFMnr/FO+FG55QhCxFMXIc6XrC3vslNy5ef3B3zv4gCttS3ee8ByMiw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-list-item": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.5.9.tgz", + "integrity": "sha512-d9Eo+vBz74SMxP0r25aqiErV256C+lGz+VWMjOoqJa6xWLM1keYy12JtGQWJi8UDVZrDskJKCHq81A0uLt27WA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-mention": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-mention/-/extension-mention-2.5.9.tgz", + "integrity": "sha512-O8LhClSkX5kUAyShrf2euN4oOusr5/niur7zvvbB7QZxn35kf+NtSM0i4nbyJQDMa7DnrFuQzkN5M/PCvMtr2w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9", + "@tiptap/suggestion": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-ordered-list": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.5.9.tgz", + "integrity": "sha512-9MsWpvVvzILuEOd/GdroF7RI7uDuE1M6at9rzsaVGvCPVHZBvu1XR3MSVK5OdiJbbJuPGttlzEFLaN/rQdCGFg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.5.9.tgz", + "integrity": "sha512-HDXGiHTJ/V85dbDMjcFj4XfqyTQZqry6V21ucMzgBZYX60X3gIn7VpQTQnnRjvULSgtfOASSJP6BELc5TyiK0w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-placeholder": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.5.9.tgz", + "integrity": "sha512-ytKmlSiebtCBXoMPE2cup48DR0rQiekXhLKLkNyt7m8tSXkaRO4eDaFqCqPEXLeQXWdhwWEoPM6Cejaaa3ztkA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.5.9.tgz", + "integrity": "sha512-QezkOZpczpl09S8lp5JL7sRkwREoPY16Y/lTvBcFKm3TZbVzYZZ/KwS0zpwK9HXTfXr8os4L9AGjQf0tHonX+w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.5.9.tgz", + "integrity": "sha512-W0pfiQUPsMkwaV5Y/wKW4cFsyXAIkyOFt7uN5u6LrZ/iW9KZ/IsDODPJDikWp0aeQnXzT9NNQULTpCjbHzzS6g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9" + } + }, + "node_modules/@tiptap/pm": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.5.9.tgz", + "integrity": "sha512-YSUaEQVtvZnGzGjif2Tl2o9utE+6tR2Djhz0EqFUcAUEVhOMk7UYUO+r/aPfcCRraIoKKuDQzyCpjKmJicjCUA==", + "dependencies": { + "prosemirror-changeset": "^2.2.1", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.5.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.0", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.22.2", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.4.1", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.4.0", + "prosemirror-trailing-node": "^2.0.9", + "prosemirror-transform": "^1.9.0", + "prosemirror-view": "^1.33.9" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/react": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.5.9.tgz", + "integrity": "sha512-NZYAslIb79oxIOFHx9T9ey5oX0aJ1uRbtT2vvrvvyRaO6fKWgAwMYN92bOu5/f2oUVGUp6l7wkYZGdjz/XP5bA==", + "dependencies": { + "@tiptap/extension-bubble-menu": "^2.5.9", + "@tiptap/extension-floating-menu": "^2.5.9", + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + } + }, + "node_modules/@tiptap/starter-kit": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.5.9.tgz", + "integrity": "sha512-nZ4V+vRayomjxUsajFMHv1iJ5SiSaEA65LAXze/CzyZXGMXfL2OLzY7wJoaVJ4BgwINuO0dOSAtpNDN6jI+6mQ==", + "dependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/extension-blockquote": "^2.5.9", + "@tiptap/extension-bold": "^2.5.9", + "@tiptap/extension-bullet-list": "^2.5.9", + "@tiptap/extension-code": "^2.5.9", + "@tiptap/extension-code-block": "^2.5.9", + "@tiptap/extension-document": "^2.5.9", + "@tiptap/extension-dropcursor": "^2.5.9", + "@tiptap/extension-gapcursor": "^2.5.9", + "@tiptap/extension-hard-break": "^2.5.9", + "@tiptap/extension-heading": "^2.5.9", + "@tiptap/extension-history": "^2.5.9", + "@tiptap/extension-horizontal-rule": "^2.5.9", + "@tiptap/extension-italic": "^2.5.9", + "@tiptap/extension-list-item": "^2.5.9", + "@tiptap/extension-ordered-list": "^2.5.9", + "@tiptap/extension-paragraph": "^2.5.9", + "@tiptap/extension-strike": "^2.5.9", + "@tiptap/extension-text": "^2.5.9" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/suggestion": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@tiptap/suggestion/-/suggestion-2.5.9.tgz", + "integrity": "sha512-s7UU0j2IRreVXrMMxsFvsNjJnZeTS1SAwsjLkN2YX+/ZQss92s0BLP3HsxEr2oFHlFye8E0qR9xjWZ4vSc9asw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.9", + "@tiptap/pm": "^2.5.9" + } + }, "node_modules/@types/async-lock": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.4.2.tgz", @@ -2701,6 +3107,11 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==" + }, "node_modules/@types/uuid": { "version": "9.0.8", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", @@ -3652,8 +4063,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-back": { "version": "3.1.0", @@ -5102,6 +5512,11 @@ "node": ">=8" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -11784,6 +12199,11 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==" + }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -12376,6 +12796,227 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/prosemirror-changeset": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.1.tgz", + "integrity": "sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==", + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-collab": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", + "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", + "dependencies": { + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.6.0.tgz", + "integrity": "sha512-xn1U/g36OqXn2tn5nGmvnnimAj/g1pUx2ypJJIe8WkVX83WyJVC5LTARaxZa2AtQRwntu9Jc5zXs9gL9svp/mg==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz", + "integrity": "sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz", + "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", + "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.4.0.tgz", + "integrity": "sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz", + "integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-markdown": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.0.tgz", + "integrity": "sha512-UziddX3ZYSYibgx8042hfGKmukq5Aljp2qoBiJRejD/8MH70siQNz5RB1TrdTPheqLMy4aCe4GYNF10/3lQS5g==", + "dependencies": { + "markdown-it": "^14.0.0", + "prosemirror-model": "^1.20.0" + } + }, + "node_modules/prosemirror-markdown/node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/prosemirror-markdown/node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/prosemirror-markdown/node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" + }, + "node_modules/prosemirror-markdown/node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + }, + "node_modules/prosemirror-menu": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz", + "integrity": "sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==", + "dependencies": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.22.3.tgz", + "integrity": "sha512-V4XCysitErI+i0rKFILGt/xClnFJaohe/wrrlT2NSZ+zk8ggQfDH4x2wNK7Gm0Hp4CIoWizvXFP7L9KMaCuI0Q==", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-schema-basic": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz", + "integrity": "sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA==", + "dependencies": { + "prosemirror-model": "^1.19.0" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.4.1.tgz", + "integrity": "sha512-jbDyaP/6AFfDfu70VzySsD75Om2t3sXTOdl5+31Wlxlg62td1haUpty/ybajSfJ1pkGadlOfwQq9kgW5IMo1Rg==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" + } + }, + "node_modules/prosemirror-state": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz", + "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "node_modules/prosemirror-tables": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.4.0.tgz", + "integrity": "sha512-fxryZZkQG12fSCNuZDrYx6Xvo2rLYZTbKLRd8rglOPgNJGMKIS8uvTt6gGC38m7UCu/ENnXIP9pEz5uDaPc+cA==", + "dependencies": { + "prosemirror-keymap": "^1.1.2", + "prosemirror-model": "^1.8.1", + "prosemirror-state": "^1.3.1", + "prosemirror-transform": "^1.2.1", + "prosemirror-view": "^1.13.3" + } + }, + "node_modules/prosemirror-trailing-node": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-2.0.9.tgz", + "integrity": "sha512-YvyIn3/UaLFlFKrlJB6cObvUhmwFNZVhy1Q8OpW/avoTbD/Y7H5EcjK4AZFKhmuS6/N6WkGgt7gWtBWDnmFvHg==", + "dependencies": { + "@remirror/core-constants": "^2.0.2", + "escape-string-regexp": "^4.0.0" + }, + "peerDependencies": { + "prosemirror-model": "^1.22.1", + "prosemirror-state": "^1.4.2", + "prosemirror-view": "^1.33.8" + } + }, + "node_modules/prosemirror-trailing-node/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.9.0.tgz", + "integrity": "sha512-5UXkr1LIRx3jmpXXNKDhv8OyAOeLTGuXNwdVfg8x27uASna/wQkr9p6fD3eupGOi4PLJfbezxTyi/7fSJypXHg==", + "dependencies": { + "prosemirror-model": "^1.21.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.33.9", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.9.tgz", + "integrity": "sha512-xV1A0Vz9cIcEnwmMhKKFAOkfIp8XmJRnaZoPqNXrPS7EK5n11Ov8V76KhR0RsfQd/SIzmWY+bg+M44A2Lx/Nnw==", + "dependencies": { + "prosemirror-model": "^1.20.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, "node_modules/protobufjs": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.2.tgz", @@ -12449,6 +13090,14 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -13006,6 +13655,11 @@ "inherits": "^2.0.1" } }, + "node_modules/rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -14009,6 +14663,14 @@ "node": ">=0.6.0" } }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -14523,6 +15185,14 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -14611,6 +15281,11 @@ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", diff --git a/package.json b/package.json index 6f2bf032..23095cae 100644 --- a/package.json +++ b/package.json @@ -446,6 +446,12 @@ }, "dependencies": { "@lancedb/lancedb": "^0.5.2", + "@tiptap/extension-mention": "^2.5.9", + "@tiptap/extension-placeholder": "^2.5.9", + "@tiptap/pm": "^2.5.9", + "@tiptap/react": "^2.5.9", + "@tiptap/starter-kit": "^2.5.9", + "@tiptap/suggestion": "^2.5.9", "@types/react": "^18.2.46", "@vscode/codicons": "^0.0.35", "@vscode/vsce": "^2.31.1", @@ -454,22 +460,23 @@ "async-lock": "^1.4.1", "b4a": "^1.6.6", "classnames": "^2.5.1", - "handlebars-loader": "^1.7.3", "handlebars": "^4.7.8", + "handlebars-loader": "^1.7.3", "hypercore-crypto": "^3.4.2", "hyperswarm": "^4.7.15", "minimatch": "^9.0.4", "node-polyfill-webpack-plugin": "^3.0.0", "onnxruntime-web": "^1.18.0", "pear-stdio": "^1.0.1", + "react": "^18.2.0", "react-dom": "^18.2.0", "react-markdown": "^9.0.1", "react-syntax-highlighter": "^15.5.0", - "react": "^18.2.0", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.0", "stream-http": "^3.2.0", "string_score": "^0.1.22", + "tippy.js": "^6.3.7", "toxe": "^1.1.0", "uuid": "^9.0.1" }, diff --git a/src/common/constants.ts b/src/common/constants.ts index 036a5d6b..6315340e 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -26,6 +26,12 @@ export const MIN_COMPLETION_CHUNKS = 2 export const MAX_EMPTY_COMPLETION_CHARS = 250 export const DEFAULT_RERANK_THRESHOLD = 0.5 +export const defaultChunkOptions = { + maxSize: 500, + minSize: 50, + overlap: 50 +} + export const EVENT_NAME = { twinngAddMessage: 'twinny-add-message', twinnyAcceptSolution: 'twinny-accept-solution', @@ -118,8 +124,8 @@ export const PROVIDER_EVENT_NAME = { updateProvider: 'twinny.update-provider' } -export const ACTIVE_CHAT_PROVIDER_STORAGE_KEY = 'twinny.active-chat-provider' export const ACTIVE_CONVERSATION_STORAGE_KEY = 'twinny.active-conversation' +export const ACTIVE_CHAT_PROVIDER_STORAGE_KEY = 'twinny.active-chat-provider' export const ACTIVE_EMBEDDINGS_PROVIDER_STORAGE_KEY = 'twinny.active-embeddings-provider' export const ACTIVE_FIM_PROVIDER_STORAGE_KEY = 'twinny.active-fim-provider' @@ -145,11 +151,13 @@ export const EXTENSION_SETTING_KEY = { export const EXTENSION_CONTEXT_NAME = { twinnyConversationHistory: 'twinnyConversationHistory', - twinnyEnableRag: 'twinnyEnableRag', twinnyGeneratingText: 'twinnyGeneratingText', twinnyManageProviders: 'twinnyManageProviders', twinnyManageTemplates: 'twinnyManageTemplates', twinnyRerankThreshold: 'twinnyRerankThreshold', + twinnyMaxChunkSize: 'twinnyMaxChunkSize', + twinnyMinChunkSize: 'twinnyMinChunkSize', + twinnyOverlapSize: 'twinnyOverlapSize', twinnySymmetryTab: 'twinnySymmetryTab' } diff --git a/src/common/types.ts b/src/common/types.ts index 83a27a81..484cf04e 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -164,7 +164,7 @@ export const apiProviders = { LMStudio: 'lmstudio', Ollama: 'ollama', Oobabooga: 'oobabooga', - OpenWebUI: 'openwebui', + OpenWebUI: 'openwebui' } as const export interface ApiModel { @@ -247,9 +247,9 @@ export interface InferenceRequest { } export interface ChunkOptions { - minSize?: number - maxSize?: number - overlap?: number + minSize: number + maxSize: number + overlap: number } export type Embedding = { diff --git a/src/extension.global.d.ts b/src/extension.global.d.ts index f859a1c8..31000c24 100644 --- a/src/extension.global.d.ts +++ b/src/extension.global.d.ts @@ -1,5 +1,6 @@ declare module 'hyperswarm' declare module 'b4a' +declare module '@tiptap/extension-placeholder' declare module 'hypercore-crypto' { const hyperCoreCrypto: { diff --git a/src/extension/chat-service.ts b/src/extension/chat-service.ts index 336ae164..0c77e244 100644 --- a/src/extension/chat-service.ts +++ b/src/extension/chat-service.ts @@ -446,14 +446,14 @@ export class ChatService { public async getRagContext( text?: string, ): Promise { - const ragContextKey = `${EVENT_NAME.twinnyWorkspaceContext}-${EXTENSION_CONTEXT_NAME.twinnyEnableRag}` - const isRagEnabled = this._context?.workspaceState.get(ragContextKey) const symmetryConnected = this._sessionManager?.get( EXTENSION_SESSION_NAME.twinnySymmetryConnection ) - if (!isRagEnabled || symmetryConnected) + const workspaceMentioned = text?.includes('@workspace') + + if (symmetryConnected || !workspaceMentioned) return null updateLoadingMessage(this._view, 'Exploring knowledge base') diff --git a/src/extension/embeddings.ts b/src/extension/embeddings.ts index 8c1960d1..dcef366b 100644 --- a/src/extension/embeddings.ts +++ b/src/extension/embeddings.ts @@ -134,9 +134,10 @@ export class EmbeddingDatabase { cancellable: true, }, async (progress) => { + if (!this._extensionContext) return const promises = filePaths.map(async (filePath) => { const content = await fs.promises.readFile(filePath, 'utf-8') - const chunks = await getDocumentSplitChunks(content, filePath) + const chunks = await getDocumentSplitChunks(content, filePath, this._extensionContext) const filePathEmbedding = await this.fetchModelEmbedding(filePath) this._filePaths.push({ diff --git a/src/extension/providers/sidebar.ts b/src/extension/providers/sidebar.ts index cea9d145..003504d5 100644 --- a/src/extension/providers/sidebar.ts +++ b/src/extension/providers/sidebar.ts @@ -15,7 +15,7 @@ import { TWINNY_COMMAND_NAME, SYMMETRY_DATA_MESSAGE, SYMMETRY_EMITTER_KEY, - SYSTEM, + SYSTEM } from '../../common/constants' import { ChatService } from '../chat-service' import { @@ -23,7 +23,7 @@ import { Message, ApiModel, ServerMessage, - InferenceRequest + InferenceRequest, } from '../../common/types' import { TemplateProvider } from '../template-provider' import { OllamaService } from '../ollama-service' @@ -85,7 +85,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { webviewView, this._db, this._sessionManager, - this.symmetryService, + this.symmetryService ) this.conversationHistory = new ConversationHistory( @@ -127,7 +127,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { }) webviewView.webview.onDidReceiveMessage( - (message: ClientMessage & ClientMessage) => { + (message) => { const eventHandlers = { [EVENT_NAME.twinnyAcceptSolution]: this.acceptSolution, [EVENT_NAME.twinnyChatMessage]: this.streamChatCompletion, @@ -142,8 +142,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { [EVENT_NAME.twinnySendLanguage]: this.getCurrentLanguage, [EVENT_NAME.twinnySendTheme]: this.getTheme, [EVENT_NAME.twinnySetGlobalContext]: this.setGlobalContext, - [EVENT_NAME.twinnySetWorkspaceContext]: - this.setTwinnyWorkspaceContext, + [EVENT_NAME.twinnySetWorkspaceContext]: this.setWorkspaceContext, [EVENT_NAME.twinnyTextSelection]: this.getSelectedText, [EVENT_NAME.twinnyWorkspaceContext]: this.getTwinnyWorkspaceContext, [EVENT_NAME.twinnySetConfigValue]: this.setConfigurationValue, @@ -153,7 +152,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { [EVENT_NAME.twinnyEmbedDocuments]: this.embedDocuments, [EVENT_NAME.twinnyConnectSymmetry]: this.connectToSymmetry, [EVENT_NAME.twinnyDisconnectSymmetry]: this.disconnectSymmetry, - [EVENT_NAME.twinnySessionContext]: this.getSessionContext + [EVENT_NAME.twinnySessionContext]: this.getSessionContext, } eventHandlers[message.type as string]?.(message) } @@ -185,22 +184,22 @@ export class SidebarProvider implements vscode.WebviewViewProvider { } } - public getConfigurationValue = (data: ClientMessage) => { - if (!data.key) return + public getConfigurationValue = (message: ClientMessage) => { + if (!message.key) return const config = vscode.workspace.getConfiguration('twinny') this.view?.webview.postMessage({ type: EVENT_NAME.twinnyGetConfigValue, value: { - data: config.get(data.key as string), - type: data.key + data: config.get(message.key as string), + type: message.key } } as ServerMessage) } - public setConfigurationValue = (data: ClientMessage) => { - if (!data.key) return + public setConfigurationValue = (message: ClientMessage) => { + if (!message.key) return const config = vscode.workspace.getConfiguration('twinny') - config.update(data.key, data.data, vscode.ConfigurationTarget.Global) + config.update(message.key, message.data, vscode.ConfigurationTarget.Global) } public fetchOllamaModels = async () => { @@ -230,14 +229,14 @@ export class SidebarProvider implements vscode.WebviewViewProvider { } as ServerMessage) } - public sendNotification = (data: ClientMessage) => { - vscode.window.showInformationMessage(data.data as string) + public sendNotification = (message: ClientMessage) => { + vscode.window.showInformationMessage(message.data as string) } - public clickSuggestion = (data: ClientMessage) => { + public clickSuggestion = (message: ClientMessage) => { vscode.commands.executeCommand( 'twinny.templateCompletion', - data.data as string + message.data as string ) } @@ -270,6 +269,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { ) ) } + this.chatService?.streamChatCompletion(data.data || []) } @@ -307,24 +307,34 @@ export class SidebarProvider implements vscode.WebviewViewProvider { }) } - public acceptSolution = (data: ClientMessage) => { + public acceptSolution = (message: ClientMessage) => { const editor = vscode.window.activeTextEditor const selection = editor?.selection if (!selection) return vscode.window.activeTextEditor?.edit((editBuilder) => { - editBuilder.replace(selection, data.data as string) + editBuilder.replace(selection, message.data as string) }) } - public createNewUntitledDocument = async (data: ClientMessage) => { + public createNewUntitledDocument = async (message: ClientMessage) => { const lang = getLanguage() const document = await vscode.workspace.openTextDocument({ - content: data.data as string, + content: message.data as string, language: lang.languageId }) await vscode.window.showTextDocument(document) } + public getGlobalContext = (message: ClientMessage) => { + const storedData = this._context?.globalState.get( + `${EVENT_NAME.twinnyGlobalContext}-${message.key}` + ) + this.view?.webview.postMessage({ + type: `${EVENT_NAME.twinnyGlobalContext}-${message.key}`, + value: storedData + }) + } + public getTheme = () => { this.view?.webview.postMessage({ type: EVENT_NAME.twinnySendTheme, @@ -370,41 +380,31 @@ export class SidebarProvider implements vscode.WebviewViewProvider { }) } - public getGlobalContext = (data: ClientMessage) => { - const storedData = this._context?.globalState.get( - `${EVENT_NAME.twinnyGlobalContext}-${data.key}` - ) - this.view?.webview.postMessage({ - type: `${EVENT_NAME.twinnyGlobalContext}-${data.key}`, - value: storedData - }) - } - - public setGlobalContext = (data: ClientMessage) => { + public setGlobalContext = (message: ClientMessage) => { this._context?.globalState.update( - `${EVENT_NAME.twinnyGlobalContext}-${data.key}`, - data.data + `${EVENT_NAME.twinnyGlobalContext}-${message.key}`, + message.data ) } - public getTwinnyWorkspaceContext = (data: ClientMessage) => { + public getTwinnyWorkspaceContext = (message: ClientMessage) => { const storedData = this._context?.workspaceState.get( - `${EVENT_NAME.twinnyWorkspaceContext}-${data.key}` + `${EVENT_NAME.twinnyWorkspaceContext}-${message.key}` ) this.view?.webview.postMessage({ - type: `${EVENT_NAME.twinnyWorkspaceContext}-${data.key}`, + type: `${EVENT_NAME.twinnyWorkspaceContext}-${message.key}`, value: storedData } as ServerMessage) } - public setTwinnyWorkspaceContext = (data: ClientMessage) => { - const value = data.data + public setWorkspaceContext = (message: ClientMessage) => { + const value = message.data this._context.workspaceState.update( - `${EVENT_NAME.twinnyWorkspaceContext}-${data.key}`, + `${EVENT_NAME.twinnyWorkspaceContext}-${message.key}`, value ) this.view?.webview.postMessage({ - type: `${EVENT_NAME.twinnyWorkspaceContext}-${data.key}`, + type: `${EVENT_NAME.twinnyWorkspaceContext}-${message.key}`, value }) } diff --git a/src/extension/utils.ts b/src/extension/utils.ts index 7d5d6dfa..583e3e67 100644 --- a/src/extension/utils.ts +++ b/src/extension/utils.ts @@ -1,5 +1,6 @@ import { ColorThemeKind, + ExtensionContext, InlineCompletionContext, InlineCompletionTriggerKind, Position, @@ -31,7 +32,9 @@ import { supportedLanguages } from '../common/languages' import { ALL_BRACKETS, CLOSING_BRACKETS, + defaultChunkOptions, EVENT_NAME, + EXTENSION_CONTEXT_NAME, LINE_BREAK_REGEX, MULTILINE_TYPES, NORMALIZE_REGEX, @@ -481,32 +484,51 @@ function getSplitChunks(node: SyntaxNode, options: ChunkOptions): string[] { return chunks } +export const getChunkOptions = ( + context: ExtensionContext | undefined +): ChunkOptions => { + if (!context) return defaultChunkOptions + const maxChunkSizeContext = `${EVENT_NAME.twinnyGlobalContext}-${EXTENSION_CONTEXT_NAME.twinnyMaxChunkSize}` + const minChunkSizeContext = `${EVENT_NAME.twinnyGlobalContext}-${EXTENSION_CONTEXT_NAME.twinnyMinChunkSize}` + const overlap = `${EVENT_NAME.twinnyGlobalContext}-${EXTENSION_CONTEXT_NAME.twinnyOverlapSize}` + + const options = { + maxSize: Number(context.globalState.get(maxChunkSizeContext)) || 500, + minSize: Number(context.globalState.get(minChunkSizeContext)) || 50, + overlap: Number(context.globalState.get(overlap)) || 50 + } + + return options +} + export async function getDocumentSplitChunks( content: string, filePath: string, - options: ChunkOptions = {} + context: ExtensionContext | undefined ): Promise { - const { minSize = 50, maxSize = 500, overlap = 50 } = options + if (!context) return [] + + const options = getChunkOptions(context) try { const parser = await getParser(filePath) if (!parser) { - return simpleChunk(content, { minSize, maxSize, overlap }) + return simpleChunk(content, options) } const tree = parser.parse(content) - const chunks = getSplitChunks(tree.rootNode, { minSize, maxSize }) + const chunks = getSplitChunks(tree.rootNode, options) - return combineChunks(chunks, { minSize, maxSize, overlap }) + return combineChunks(chunks, options) } catch (error) { console.error(`Error parsing file ${filePath}: ${error}`) - return simpleChunk(content, { minSize, maxSize, overlap }) + return simpleChunk(content, options) } } function combineChunks(chunks: string[], options: ChunkOptions): string[] { - const { minSize = 50, maxSize = 500, overlap = 50 } = options + const { minSize, maxSize, overlap } = options const result: string[] = [] let currentChunk = '' diff --git a/src/webview/chat.tsx b/src/webview/chat.tsx index ff30f18f..2b56b1e7 100644 --- a/src/webview/chat.tsx +++ b/src/webview/chat.tsx @@ -1,19 +1,23 @@ -import { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { VSCodeButton, VSCodePanelView, VSCodeBadge, - VSCodeDivider, + VSCodeDivider } from '@vscode/webview-ui-toolkit/react' +import { useEditor, EditorContent, Extension, Editor } from '@tiptap/react' +import StarterKit from '@tiptap/starter-kit' +import Placeholder from '@tiptap/extension-placeholder' +import Mention, { MentionPluginKey } from '@tiptap/extension-mention' +import { suggestion } from './suggestion' import { ASSISTANT, WORKSPACE_STORAGE_KEY, EVENT_NAME, USER, - SYMMETRY_EMITTER_KEY, - EXTENSION_CONTEXT_NAME + SYMMETRY_EMITTER_KEY } from '../common/constants' import useAutosizeTextArea, { @@ -23,12 +27,7 @@ import useAutosizeTextArea, { useTheme, useWorkSpaceContext } from './hooks' -import { - DisabledAutoScrollIcon, - DisabledRAGIcon, - EnabledAutoScrollIcon, - EnabledRAGIcon -} from './icons' +import { DisabledAutoScrollIcon, EnabledAutoScrollIcon } from './icons' import { Suggestions } from './suggestions' import { @@ -43,11 +42,38 @@ import { ProviderSelect } from './provider-select' import { EmbeddingOptions } from './embedding-options' import ChatLoader from './chat-loader' +const CustomKeyMap = Extension.create({ + name: 'customKeymap', + + addKeyboardShortcuts() { + return { + Enter: ({ editor }) => { + const mentionState = MentionPluginKey.getState(editor.state) + if (mentionState && mentionState.active) { + return false + } + this.options.handleSubmitForm(editor.getText()) + this.options.clearEditor() + return true + }, + 'Mod-Enter': ({ editor }) => { + editor.commands.insertContent('\n') + return true + }, + 'Shift-Enter': ({ editor }) => { + editor.commands.insertContent('\n') + return true + } + } + } +}) + // eslint-disable-next-line @typescript-eslint/no-explicit-any const global = globalThis as any export const Chat = () => { const [inputText, setInputText] = useState('') const generatingRef = useRef(false) + const editorRef = useRef(null) const stopRef = useRef(false) const theme = useTheme() const [loading, setLoading] = useState(false) @@ -66,8 +92,6 @@ export const Chat = () => { } = useWorkSpaceContext(WORKSPACE_STORAGE_KEY.showEmbeddingOptions) const { conversation, saveLastConversation, setActiveConversation } = useConversationHistory() - const { context: enableRagContext, setContext: setEnableRagContext } = - useWorkSpaceContext(EXTENSION_CONTEXT_NAME.twinnyEnableRag) const chatRef = useRef(null) useAutosizeTextArea(chatRef, inputText) @@ -202,24 +226,35 @@ export const Chat = () => { }, 200) } - const handleSubmitForm = (input: string) => { - if (input) { - setLoading(true) - setInputText('') - global.vscode.postMessage({ - type: EVENT_NAME.twinnyChatMessage, - data: [ - ...(messages || []), - { - role: USER, - content: input + const handleSubmitForm = useCallback( + (input: string) => { + if (input) { + setLoading(true) + setInputText('') + global.vscode.postMessage({ + type: EVENT_NAME.twinnyChatMessage, + data: [ + ...(messages || []), + { + role: USER, + content: input + } + ] + } as ClientMessage) + setMessages((prev) => [...(prev || []), { role: USER, content: input }]) + setTimeout(() => { + if (markdownRef.current) { + markdownRef.current.scrollTop = markdownRef.current.scrollHeight } - ] - } as ClientMessage) - setMessages((prev) => [...(prev || []), { role: USER, content: input }]) - scrollToBottom() - } - } + }, 200) + } + }, + [messages] + ) + + const clearEditor = useCallback(() => { + editorRef.current?.commands.clearContent() + }, []) const handleToggleAutoScroll = () => { setAutoScrollContext((prev) => { @@ -269,17 +304,6 @@ export const Chat = () => { } } - const handleToggleRag = (): void => { - setEnableRagContext((prev) => { - global.vscode.postMessage({ - type: EVENT_NAME.twinnySetWorkspaceContext, - key: EXTENSION_CONTEXT_NAME.twinnyEnableRag, - data: !prev - } as ClientMessage) - return !prev - }) - } - useEffect(() => { window.addEventListener('message', messageEventHandler) chatRef.current?.focus() @@ -295,6 +319,30 @@ export const Chat = () => { } }, [conversation?.id, autoScrollContext, showProvidersContext]) + const editor = useEditor({ + extensions: [ + StarterKit, + Placeholder.configure({ + placeholder: 'How can twinny help you today?' + }), + Mention.configure({ + HTMLAttributes: { + class: 'mention' + }, + suggestion + }), + CustomKeyMap.configure({ + handleSubmitForm, + clearEditor + }) + ], + content: inputText + }) + + if (editor && !editorRef.current) { + editorRef.current = editor + } + return (
@@ -355,14 +403,6 @@ export const Chat = () => { > - - {enableRagContext ? : } - - {selection?.length}
{generatingRef.current && ( @@ -408,28 +448,10 @@ export const Chat = () => {
-