From b41bde7c31189640c36af3b896d9763f8abfd971 Mon Sep 17 00:00:00 2001 From: rjmacarthy Date: Mon, 12 Aug 2024 14:25:25 +0100 Subject: [PATCH] updates 3.14.3 --- package-lock.json | 271 +++++++++++------------------- package.json | 4 +- src/common/constants.ts | 15 +- src/extension/chat-service.ts | 82 ++++++--- src/extension/embeddings.ts | 68 ++++++-- src/extension/utils.ts | 15 +- src/webview/chat.tsx | 56 +++--- src/webview/embedding-options.tsx | 74 +++++++- src/webview/index.module.css | 11 +- 9 files changed, 333 insertions(+), 263 deletions(-) diff --git a/package-lock.json b/package-lock.json index c1615638..9ae9d662 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "twinny", - "version": "3.14.2", + "version": "3.14.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "twinny", - "version": "3.14.2", + "version": "3.14.3", "cpu": [ "x64", "arm64" @@ -18,7 +18,7 @@ "win32" ], "dependencies": { - "@lancedb/lancedb": "^0.5.2", + "@lancedb/lancedb": "^0.9.0", "@tiptap/extension-mention": "^2.5.9", "@tiptap/extension-placeholder": "^2.5.9", "@tiptap/pm": "^2.5.9", @@ -2183,9 +2183,9 @@ } }, "node_modules/@lancedb/lancedb": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@lancedb/lancedb/-/lancedb-0.5.2.tgz", - "integrity": "sha512-0cEE07E5osctkM/C/9rAFnXS5FxdVFOiUFZt4g+E0qsS4oTLYn7IhQTQL/LfI7N7XjGyLQ3SkRfl8PCXHLMhdQ==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@lancedb/lancedb/-/lancedb-0.9.0.tgz", + "integrity": "sha512-roIBK6JJq4AkvVmLG4orZ/SXdpzPLnArhKTK+4cG/Nso9k2y2Wk5DsFStqzNmO7ko1phiCJJlmtwPLr787nV/Q==", "cpu": [ "x64", "arm64" @@ -2196,25 +2196,27 @@ "win32" ], "dependencies": { - "apache-arrow": "^15.0.0", - "openai": "^4.29.2", + "axios": "^1.7.2", "reflect-metadata": "^0.2.2" }, "engines": { "node": ">= 18" }, "optionalDependencies": { - "@lancedb/lancedb-darwin-arm64": "0.5.2", - "@lancedb/lancedb-darwin-x64": "0.5.2", - "@lancedb/lancedb-linux-arm64-gnu": "0.5.2", - "@lancedb/lancedb-linux-x64-gnu": "0.5.2", - "@lancedb/lancedb-win32-x64-msvc": "0.5.2" + "@lancedb/lancedb-darwin-arm64": "0.9.0", + "@lancedb/lancedb-darwin-x64": "0.9.0", + "@lancedb/lancedb-linux-arm64-gnu": "0.9.0", + "@lancedb/lancedb-linux-x64-gnu": "0.9.0", + "@lancedb/lancedb-win32-x64-msvc": "0.9.0" + }, + "peerDependencies": { + "apache-arrow": ">=13.0.0 <=17.0.0" } }, "node_modules/@lancedb/lancedb-darwin-arm64": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@lancedb/lancedb-darwin-arm64/-/lancedb-darwin-arm64-0.5.2.tgz", - "integrity": "sha512-tEtwM+c3D6imAh1wE0nBGYFwRILeX3E1/mNjUjIV8panlfvO2SMJuDORRjtfKNt1GghfVQ5QFu94cL+xSzWjow==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@lancedb/lancedb-darwin-arm64/-/lancedb-darwin-arm64-0.9.0.tgz", + "integrity": "sha512-w/lbpjCNNfzMWL0rgOdxjc6dQWrgxt7YtBcU/a5CYUkuj6I+EcBhp7VtX7t+8smF1pIJqeMPakhHe3SrkA5ZRQ==", "cpu": [ "arm64" ], @@ -2227,9 +2229,9 @@ } }, "node_modules/@lancedb/lancedb-darwin-x64": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@lancedb/lancedb-darwin-x64/-/lancedb-darwin-x64-0.5.2.tgz", - "integrity": "sha512-Z/MRAleGm/us2XTb/L2WalIGKO8L6mumB7lqAhXsKiz06aYfE3+L8eEfSDcBdNfMv9Le1vA44kIJlnBX1ADV+g==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@lancedb/lancedb-darwin-x64/-/lancedb-darwin-x64-0.9.0.tgz", + "integrity": "sha512-ENnWvwEEUMozlfGt3Q+CLyHrk5PTjYSq9adnKKwfhvdNKXtLLibSpIj9VyTDa+9rfJWpdLKFD28Tsh/6Q+AHzA==", "cpu": [ "x64" ], @@ -2242,9 +2244,9 @@ } }, "node_modules/@lancedb/lancedb-linux-arm64-gnu": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@lancedb/lancedb-linux-arm64-gnu/-/lancedb-linux-arm64-gnu-0.5.2.tgz", - "integrity": "sha512-/menmFjQD877YAiYts8SRCqH52QSeNAwzv2n1CBV6XZGeH5vH+Jq7JTwXdllfhfjytl26xfJJ/zvCIJ7DuUN/Q==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@lancedb/lancedb-linux-arm64-gnu/-/lancedb-linux-arm64-gnu-0.9.0.tgz", + "integrity": "sha512-GqduIR6yTBxTu8kCMPofeV4vUSDdzSu43AbxwtuErPIGX6a+O8100OQ3kNFNOICwjpdcRjS5umd5POSxz2H59w==", "cpu": [ "arm64" ], @@ -2257,9 +2259,9 @@ } }, "node_modules/@lancedb/lancedb-linux-x64-gnu": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@lancedb/lancedb-linux-x64-gnu/-/lancedb-linux-x64-gnu-0.5.2.tgz", - "integrity": "sha512-spLVfnDexIifg8UPocksjlUCKcfyKeWfoY2w/WJr1sVdarVorPOZwQ0zB5zrNq7tD4PJB9oGUCYt3hbj2+D/lQ==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@lancedb/lancedb-linux-x64-gnu/-/lancedb-linux-x64-gnu-0.9.0.tgz", + "integrity": "sha512-KfEUoewxGkvAuX3ctJQ0cH4f5AK1QwxHq7ZGj5FfFls68JjewkUgsoeaEDvmhtC5WKq44Bw6N09eWJ1eWSZn3w==", "cpu": [ "x64" ], @@ -2272,9 +2274,9 @@ } }, "node_modules/@lancedb/lancedb-win32-x64-msvc": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@lancedb/lancedb-win32-x64-msvc/-/lancedb-win32-x64-msvc-0.5.2.tgz", - "integrity": "sha512-obyTCSjoIyHVaDpnNrIBoiw7Y2jLBfZs3VzbyigjI3ylZRbvVGKmKO/Vwc2kuT07/vKPysHkrS6o1AQYRRLzhw==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@lancedb/lancedb-win32-x64-msvc/-/lancedb-win32-x64-msvc-0.9.0.tgz", + "integrity": "sha512-lEFoGudbzZ4RhbhdMoLCDXcDhiVTInK1nSz5/GRIJ8O4j91OOlYu6jDT/mw9II2ghtW7YmpoEGOuon1fqmHn1A==", "cpu": [ "x64" ], @@ -2480,6 +2482,7 @@ "version": "0.5.12", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.12.tgz", "integrity": "sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==", + "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -2919,12 +2922,14 @@ "node_modules/@types/command-line-args": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.3.tgz", - "integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==" + "integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==", + "peer": true }, "node_modules/@types/command-line-usage": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.4.tgz", - "integrity": "sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==" + "integrity": "sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==", + "peer": true }, "node_modules/@types/debug": { "version": "4.1.12", @@ -3043,15 +3048,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.104.tgz", "integrity": "sha512-OF3keVCbfPlkzxnnDBUZJn1RiCJzKeadjiW0xTEb0G1SUJ5gDVb3qnzZr2T4uIFvsbKJbXy1v2DN7e2zaEY7jQ==" }, - "node_modules/@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", @@ -3889,17 +3885,6 @@ "node": ">= 14" } }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4037,6 +4022,7 @@ "version": "15.0.2", "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-15.0.2.tgz", "integrity": "sha512-RvwlFxLRpO405PLGffx4N2PYLiF7FD86Q1hHl6J2XCWiq+tTCzpb9ngFw0apFDcXZBMpCzMuwAvA7hjyL1/73A==", + "peer": true, "dependencies": { "@swc/helpers": "^0.5.2", "@types/command-line-args": "^5.2.1", @@ -4056,6 +4042,7 @@ "version": "20.14.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.14.tgz", "integrity": "sha512-d64f00982fS9YoOgJkAMolK7MN8Iq3TDdVjchbYHdEmjth/DHowx82GnoA+tVUAN+7vxfYUgAzi+JXbKNd2SDQ==", + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -4069,6 +4056,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "peer": true, "engines": { "node": ">=6" } @@ -4138,6 +4126,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", + "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/azure-devops-node-api": { "version": "12.5.0", "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", @@ -4790,6 +4788,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "peer": true, "dependencies": { "chalk": "^4.1.2" }, @@ -4804,6 +4803,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4818,6 +4818,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4833,6 +4834,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4843,12 +4845,14 @@ "node_modules/chalk-template/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "peer": true }, "node_modules/chalk-template/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -5211,6 +5215,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "peer": true, "dependencies": { "array-back": "^3.1.0", "find-replace": "^3.0.0", @@ -5225,6 +5230,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.3.tgz", "integrity": "sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==", + "peer": true, "dependencies": { "array-back": "^6.2.2", "chalk-template": "^0.4.0", @@ -5239,6 +5245,7 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "peer": true, "engines": { "node": ">=12.17" } @@ -5247,6 +5254,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==", + "peer": true, "engines": { "node": ">=12.17" } @@ -6794,6 +6802,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "peer": true, "dependencies": { "array-back": "^3.0.1" }, @@ -6907,7 +6916,8 @@ "node_modules/flatbuffers": { "version": "23.5.26", "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", - "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" + "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==", + "peer": true }, "node_modules/flatted": { "version": "3.3.1", @@ -6916,6 +6926,25 @@ "dev": true, "peer": true }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -6953,11 +6982,6 @@ "node": ">= 6" } }, - "node_modules/form-data-encoder": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", - "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" - }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -6966,18 +6990,6 @@ "node": ">=0.4.x" } }, - "node_modules/formdata-node": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", - "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", - "dependencies": { - "node-domexception": "1.0.0", - "web-streams-polyfill": "4.0.0-beta.3" - }, - "engines": { - "node": ">= 12.20" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -7629,14 +7641,6 @@ "node": ">=10.17.0" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/hypercore-crypto": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/hypercore-crypto/-/hypercore-crypto-3.4.2.tgz", @@ -9729,6 +9733,7 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz", "integrity": "sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==", + "peer": true, "engines": { "node": ">=0.8" } @@ -10235,7 +10240,8 @@ "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "peer": true }, "node_modules/lodash.includes": { "version": "4.3.0", @@ -11738,43 +11744,6 @@ "dev": true, "optional": true }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-gyp-build": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", @@ -12035,39 +12004,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openai": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.55.3.tgz", - "integrity": "sha512-/IUDdK5w3aB1Kd88Ml7w5F+EkVM5aXlrY+lSpWXdIPL18CmGkC7lV9HFJ7beR0OUSFLFT0qmWvMynqtbMF06/Q==", - "dependencies": { - "@types/node": "^18.11.18", - "@types/node-fetch": "^2.6.4", - "abort-controller": "^3.0.0", - "agentkeepalive": "^4.2.1", - "form-data-encoder": "1.7.2", - "formdata-node": "^4.3.2", - "node-fetch": "^2.6.7" - }, - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "zod": "^3.23.8" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } - } - }, - "node_modules/openai/node_modules/@types/node": { - "version": "18.19.43", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.43.tgz", - "integrity": "sha512-Mw/YlgXnyJdEwLoFv2dpuJaDFriX+Pc+0qOBJ57jC1H6cDxIj2xc5yUrdtArDVG0m+KV6622a4p2tenEqB3C/g==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -13053,6 +12989,11 @@ "unslab": "^1.3.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -14349,6 +14290,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz", "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==", + "peer": true, "dependencies": { "array-back": "^6.2.2", "wordwrapjs": "^5.1.0" @@ -14361,6 +14303,7 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "peer": true, "engines": { "node": ">=12.17" } @@ -14715,11 +14658,6 @@ "toxe": "^1.0.2" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, "node_modules/tree-sitter-wasms": { "version": "0.1.11", "resolved": "https://registry.npmjs.org/tree-sitter-wasms/-/tree-sitter-wasms-0.1.11.tgz", @@ -14950,6 +14888,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "peer": true, "engines": { "node": ">=8" } @@ -14994,7 +14933,8 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "peer": true }, "node_modules/unicorn-magic": { "version": "0.1.0", @@ -15316,25 +15256,12 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/web-streams-polyfill": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", - "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", - "engines": { - "node": ">= 14" - } - }, "node_modules/web-tree-sitter": { "version": "0.22.6", "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.22.6.tgz", "integrity": "sha512-hS87TH71Zd6mGAmYCvlgxeGDjqd9GTeqXNqTT+u0Gs51uIozNIaaq/kUAbV/Zf56jb2ZOyG8BxZs2GG9wbLi6Q==", "dev": true }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, "node_modules/webpack": { "version": "5.93.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", @@ -15409,15 +15336,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -15469,6 +15387,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz", "integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==", + "peer": true, "engines": { "node": ">=12.17" } diff --git a/package.json b/package.json index 709aa97d..47e54084 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "twinny", "displayName": "twinny - AI Code Completion and Chat", "description": "Locally hosted AI code completion plugin for vscode", - "version": "3.14.2", + "version": "3.14.3", "icon": "assets/icon.png", "keywords": [ "code-inference", @@ -445,7 +445,7 @@ "web-tree-sitter": "^0.22.1" }, "dependencies": { - "@lancedb/lancedb": "^0.5.2", + "@lancedb/lancedb": "^0.9.0", "@tiptap/extension-mention": "^2.5.9", "@tiptap/extension-placeholder": "^2.5.9", "@tiptap/pm": "^2.5.9", diff --git a/src/common/constants.ts b/src/common/constants.ts index 6315340e..60f2713e 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -158,6 +158,9 @@ export const EXTENSION_CONTEXT_NAME = { twinnyMaxChunkSize: 'twinnyMaxChunkSize', twinnyMinChunkSize: 'twinnyMinChunkSize', twinnyOverlapSize: 'twinnyOverlapSize', + twinnyRelevantFilePaths: 'twinnyRelevantFilePaths', + twinnyRelevantCodeSnippets: 'twinnyRelevantCodeSnippets', + twinnyVectorSearchMetric : 'twinnyVectorSearchMetric', twinnySymmetryTab: 'twinnySymmetryTab' } @@ -401,6 +404,16 @@ export const EMBEDDING_IGNORE_LIST = [ 'yml' ] +export const DEFAULT_RELEVANT_FILE_COUNT = 10 +export const DEFAULT_RELEVANT_CODE_COUNT = 5 +export const DEFAULT_VECTOR_SEARCH_METRIC = 'l2' + +export const EMBEDDING_METRICS = [ + 'cosine', + 'l2', + 'dot' +] + export const MULTILINE_OUTSIDE = [ 'class_body', 'class', @@ -428,9 +441,7 @@ export const MULTILINE_TYPES = [...MULTILINE_OUTSIDE, ...MULTILINE_INSIDE] export const MULTI_LINE_DELIMITERS = ['\n\n', '\r\n\r\n'] -export const RELEVANT_FILE_COUNT = 10 // todo make this configurable -export const RELEVANT_CODE_COUNT = 5 // todo make this configurable export const SYMMETRY_DATA_MESSAGE = { disconnect: 'disconnect', diff --git a/src/extension/chat-service.ts b/src/extension/chat-service.ts index 0c77e244..6c513303 100644 --- a/src/extension/chat-service.ts +++ b/src/extension/chat-service.ts @@ -10,17 +10,18 @@ import * as path from 'path' import * as fs from 'fs/promises' import { - EXTENSION_CONTEXT_NAME, - EVENT_NAME, - WEBUI_TABS, ACTIVE_CHAT_PROVIDER_STORAGE_KEY, + DEFAULT_RELEVANT_CODE_COUNT, + DEFAULT_RELEVANT_FILE_COUNT, + DEFAULT_RERANK_THRESHOLD, + DEFAULT_VECTOR_SEARCH_METRIC, + EVENT_NAME, + EXTENSION_CONTEXT_NAME, + EXTENSION_SESSION_NAME, + SYMMETRY_EMITTER_KEY, SYSTEM, USER, - RELEVANT_FILE_COUNT, - RELEVANT_CODE_COUNT, - SYMMETRY_EMITTER_KEY, - DEFAULT_RERANK_THRESHOLD, - EXTENSION_SESSION_NAME + WEBUI_TABS } from '../common/constants' import { StreamResponse, @@ -28,8 +29,7 @@ import { ServerMessage, TemplateData, Message, - StreamRequestOptions, - EmbeddedDocument + StreamRequestOptions } from '../common/types' import { getChatDataFromProvider, @@ -56,7 +56,6 @@ export class ChatService { private _context?: ExtensionContext private _controller?: AbortController private _db?: EmbeddingDatabase - private _documents: EmbeddedDocument[] = [] private _keepAlive = this._config.get('keepAlive') as string | number private _numPredictChat = this._config.get('numPredictChat') as number private _promptTemplate = '' @@ -121,9 +120,25 @@ export class ChatService { if (!embedding) return [] + const relevantFileCountContext = `${EVENT_NAME.twinnyGlobalContext}-${EXTENSION_CONTEXT_NAME.twinnyRelevantFilePaths}` + const stored = this._context?.globalState.get( + relevantFileCountContext + ) as number + const relevantFileCount = Number(stored) || DEFAULT_RELEVANT_FILE_COUNT + + const storedMetric = this._context?.globalState.get( + `${EVENT_NAME.twinnyGlobalContext}-${EXTENSION_CONTEXT_NAME.twinnyVectorSearchMetric}` + ) as number + + const metric = storedMetric || DEFAULT_VECTOR_SEARCH_METRIC + const filePaths = - (await this._db.getDocuments(embedding, RELEVANT_FILE_COUNT, table)) || - [] + (await this._db.getDocuments( + embedding, + relevantFileCount, + table, + metric as 'cosine' | 'l2' | 'dot' + )) || [] if (!filePaths.length) return [] @@ -209,20 +224,27 @@ export class ChatService { const rerankThreshold = this.getRerankThreshold() if (await this._db.hasEmbeddingTable(table)) { + const relevantCodeCountContext = `${EVENT_NAME.twinnyGlobalContext}-${EXTENSION_CONTEXT_NAME.twinnyRelevantCodeSnippets}` + const stored = this._context?.globalState.get( + relevantCodeCountContext + ) as number + const relevantCodeCount = Number(stored) || DEFAULT_RELEVANT_CODE_COUNT + const embedding = await this._db.fetchModelEmbedding(text) if (!embedding) return '' - const query = relevantFiles?.length - ? `file IN ("${relevantFiles.map((file) => file[0]).join('","')}")` - : '' + const storedMetric = this._context?.globalState.get( + `${EVENT_NAME.twinnyGlobalContext}-${EXTENSION_CONTEXT_NAME.twinnyVectorSearchMetric}` + ) as number + const metric = storedMetric || DEFAULT_VECTOR_SEARCH_METRIC const documents = (await this._db.getDocuments( embedding, - RELEVANT_CODE_COUNT, + relevantCodeCount, table, - query + metric as 'cosine' | 'l2' | 'dot' )) || [] const documentScores = await this._reranker.rerank( @@ -443,23 +465,21 @@ export class ChatService { } as ServerMessage) } - public async getRagContext( - text?: string, - ): Promise { - + public async getRagContext(text?: string): Promise { const symmetryConnected = this._sessionManager?.get( EXTENSION_SESSION_NAME.twinnySymmetryConnection ) const workspaceMentioned = text?.includes('@workspace') - if (symmetryConnected || !workspaceMentioned) - return null + if (symmetryConnected || !workspaceMentioned) return null updateLoadingMessage(this._view, 'Exploring knowledge base') - const relevantFiles = await this.getRelevantFiles(text) - const relevantCode = await this.getRelevantCode(text, relevantFiles) + const prompt = text?.replace(/@workspace/g, '') + + const relevantFiles = await this.getRelevantFiles(prompt) + const relevantCode = await this.getRelevantCode(prompt, relevantFiles) let combinedContext = '' @@ -507,6 +527,9 @@ export class ChatService { } const ragContext = await this.getRagContext(text) + + const cleanedText = text?.replace(/@workspace/g, '').trim() + if (ragContext) { additionalContext += `Additional Context:\n${ragContext}\n\n` } @@ -514,13 +537,16 @@ export class ChatService { const updatedMessages = [systemMessage, ...messages.slice(0, -1)] if (additionalContext) { - const lastMessageContent = `${text}\n\n${additionalContext.trim()}` + const lastMessageContent = `${cleanedText}\n\n${additionalContext.trim()}` updatedMessages.push({ role: USER, content: lastMessageContent }) } else { - updatedMessages.push(lastMessage) + updatedMessages.push({ + ...lastMessage, + content: cleanedText + }) } updateLoadingMessage(this._view, 'Thinking') const request = this.buildStreamRequest(updatedMessages) diff --git a/src/extension/embeddings.ts b/src/extension/embeddings.ts index dcef366b..6ebd6f0e 100644 --- a/src/extension/embeddings.ts +++ b/src/extension/embeddings.ts @@ -18,6 +18,9 @@ import { import { TwinnyProvider } from './provider-manager' import { getDocumentSplitChunks } from './utils' import { IntoVector } from '@lancedb/lancedb/dist/arrow' +import { Logger } from '../common/logger' + +const logger = new Logger() export class EmbeddingDatabase { private _config = vscode.workspace.getConfiguration('twinny') @@ -87,14 +90,16 @@ export class EmbeddingDatabase { private getAllFilePaths = async (dirPath: string): Promise => { let filePaths: string[] = [] - const dirents = await fs.promises.readdir(dirPath, { - withFileTypes: true - }) - const gitIgnoredFiles = this.readGitIgnoreFile() + const dirents = await fs.promises.readdir(dirPath, { withFileTypes: true }) + const gitIgnoredFiles = this.readGitIgnoreFile() || [] const submodules = this.readGitSubmodulesFile() + const rootPath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || '' + for (const dirent of dirents) { const fullPath = path.join(dirPath, dirent.name) + const relativePath = path.relative(rootPath, fullPath) + if (this.getIgnoreDirectory(dirent.name)) continue if (submodules?.some((submodule) => fullPath.includes(submodule))) { @@ -102,11 +107,15 @@ export class EmbeddingDatabase { } if ( - gitIgnoredFiles?.some( - (pattern) => - minimatch(fullPath, pattern, { dot: true }) && + gitIgnoredFiles.some((pattern) => { + const isIgnored = + minimatch(relativePath, pattern, { dot: true, matchBase: true }) && !pattern.startsWith('!') - ) + if (isIgnored) { + logger.log(`Ignoring ${relativePath} due to pattern: ${pattern}`) + } + return isIgnored + }) ) { continue } @@ -131,13 +140,17 @@ export class EmbeddingDatabase { { location: vscode.ProgressLocation.Notification, title: 'Embedding', - cancellable: true, + 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, this._extensionContext) + const chunks = await getDocumentSplitChunks( + content, + filePath, + this._extensionContext + ) const filePathEmbedding = await this.fetchModelEmbedding(filePath) this._filePaths.push({ @@ -207,11 +220,12 @@ export class EmbeddingDatabase { vector: IntoVector, limit: number, tableName: string, + metric: 'cosine' | 'l2' | 'dot' = 'cosine', where?: string ): Promise { try { const table = await this._db?.openTable(tableName) - const query = await table?.search(vector).limit(limit) + const query = table?.search(vector).limit(limit).distanceType(metric) // add type assertion if (where) query?.where(where) return query?.toArray() } catch (e) { @@ -232,14 +246,36 @@ export class EmbeddingDatabase { private readGitIgnoreFile(): string[] | undefined { try { const folders = vscode.workspace.workspaceFolders - if (!folders || folders.length === 0) return undefined + if (!folders || folders.length === 0) { + console.log('No workspace folders found') + return undefined + } + const rootPath = folders[0].uri.fsPath - if (!rootPath) return undefined + if (!rootPath) { + console.log('Root path is undefined') + return undefined + } + const gitIgnoreFilePath = path.join(rootPath, '.gitignore') - if (!fs.existsSync(gitIgnoreFilePath)) return undefined - const ignoreFileContent = fs.readFileSync(gitIgnoreFilePath).toString() - return ignoreFileContent.split('\n').filter((line: string) => line !== '') + if (!fs.existsSync(gitIgnoreFilePath)) { + console.log('.gitignore file not found at', gitIgnoreFilePath) + return undefined + } + + const ignoreFileContent = fs.readFileSync(gitIgnoreFilePath, 'utf8') + return ignoreFileContent + .split('\n') + .map((line) => line.trim()) + .filter((line) => line !== '' && !line.startsWith('#')) + .map((pattern) => { + if (pattern.endsWith('/')) { + return pattern + '**' + } + return pattern + }) } catch (e) { + console.error('Error reading .gitignore file:', e) return undefined } } diff --git a/src/extension/utils.ts b/src/extension/utils.ts index 583e3e67..4e793ab1 100644 --- a/src/extension/utils.ts +++ b/src/extension/utils.ts @@ -495,7 +495,7 @@ export const getChunkOptions = ( const options = { maxSize: Number(context.globalState.get(maxChunkSizeContext)) || 500, minSize: Number(context.globalState.get(minChunkSizeContext)) || 50, - overlap: Number(context.globalState.get(overlap)) || 50 + overlap: Number(context.globalState.get(overlap)) || 10 } return options @@ -519,7 +519,6 @@ export async function getDocumentSplitChunks( const tree = parser.parse(content) const chunks = getSplitChunks(tree.rootNode, options) - return combineChunks(chunks, options) } catch (error) { console.error(`Error parsing file ${filePath}: ${error}`) @@ -611,12 +610,12 @@ export const logStreamOptions = (opts: any) => { Streaming response from ${opts.options.hostname}:${opts.options.port}.\n\ Request body:\n${JSON.stringify(opts.body, null, 2)}\n\n Request options:\n${JSON.stringify(opts.options, null, 2)}\n\n -Number characters in all messages = ${opts.body.messages?.reduce( - (acc: number, msg: Message) => { +Number characters in all messages = ${ + opts.body.messages && + opts.body.messages?.reduce((acc: number, msg: Message) => { return msg.content?.length ? acc + msg.content?.length : 0 - }, - 0 - )}\n\n - ` + }, 0) + }\n\n + `.trim() ) } diff --git a/src/webview/chat.tsx b/src/webview/chat.tsx index 2b56b1e7..a0e04f44 100644 --- a/src/webview/chat.tsx +++ b/src/webview/chat.tsx @@ -71,7 +71,6 @@ const CustomKeyMap = Extension.create({ // 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) @@ -94,7 +93,6 @@ export const Chat = () => { useConversationHistory() const chatRef = useRef(null) - useAutosizeTextArea(chatRef, inputText) const scrollToBottom = () => { if (!autoScrollContext) return @@ -226,31 +224,29 @@ export const Chat = () => { }, 200) } - 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 + const handleSubmitForm = () => { + const input = editor?.getText() + if (input) { + setLoading(true) + clearEditor() + global.vscode.postMessage({ + type: EVENT_NAME.twinnyChatMessage, + data: [ + ...(messages || []), + { + role: USER, + content: input } - }, 200) - } - }, - [messages] - ) + ] + } as ClientMessage) + setMessages((prev) => [...(prev || []), { role: USER, content: input }]) + setTimeout(() => { + if (markdownRef.current) { + markdownRef.current.scrollTop = markdownRef.current.scrollHeight + } + }, 200) + } + } const clearEditor = useCallback(() => { editorRef.current?.commands.clearContent() @@ -306,7 +302,7 @@ export const Chat = () => { useEffect(() => { window.addEventListener('message', messageEventHandler) - chatRef.current?.focus() + editor?.commands.focus() scrollToBottom() return () => { window.removeEventListener('message', messageEventHandler) @@ -336,9 +332,10 @@ export const Chat = () => { clearEditor }) ], - content: inputText }) + useAutosizeTextArea(chatRef, editor?.getText() || '') + if (editor && !editorRef.current) { editorRef.current = editor } @@ -403,6 +400,7 @@ export const Chat = () => { > + {selection?.length}
{generatingRef.current && ( @@ -455,7 +453,7 @@ export const Chat = () => { />
handleSubmitForm(inputText)} + onClick={() => handleSubmitForm()} className={styles.chatSubmit} > diff --git a/src/webview/embedding-options.tsx b/src/webview/embedding-options.tsx index bfabd131..2c8edbca 100644 --- a/src/webview/embedding-options.tsx +++ b/src/webview/embedding-options.tsx @@ -6,7 +6,11 @@ import { VSCodeTextField } from '@vscode/webview-ui-toolkit/react' -import { EVENT_NAME, EXTENSION_CONTEXT_NAME } from '../common/constants' +import { + EMBEDDING_METRICS, + EVENT_NAME, + EXTENSION_CONTEXT_NAME +} from '../common/constants' import { ClientMessage } from '../common/types' import { useGlobalContext, useProviders } from './hooks' import styles from './index.module.css' @@ -35,6 +39,15 @@ export const EmbeddingOptions = () => { const { context: overlap = '20', setContext: setOverlap } = useGlobalContext(EXTENSION_CONTEXT_NAME.twinnyOverlapSize) + const { context: codeSnippets = '5', setContext: setRelevantCodeSnippets } = + useGlobalContext(EXTENSION_CONTEXT_NAME.twinnyRelevantCodeSnippets) + + const { context: filePaths = '10', setContext: setRelevantFilePaths } = + useGlobalContext(EXTENSION_CONTEXT_NAME.twinnyRelevantFilePaths) + + const { context: metric = 'l2', setContext: setMetric } = + useGlobalContext(EXTENSION_CONTEXT_NAME.twinnyVectorSearchMetric) + const embeddingProviders = Object.values(getProvidersByType('embedding')) const handleEmbedDocuments = () => { @@ -60,6 +73,20 @@ export const EmbeddingOptions = () => { setMinChunkSize(value) } + const handleRelevantCodeSnippetsChange = ( + e: Event | FormEvent + ) => { + const event = e as unknown as React.ChangeEvent + const { value } = event.target + setRelevantCodeSnippets(value) + } + + const handleRelevantFilepathsChange = (e: Event | FormEvent) => { + const event = e as unknown as React.ChangeEvent + const { value } = event.target + setRelevantFilePaths(value) + } + const handleOverlapSizeChange = (e: Event | FormEvent) => { const event = e as unknown as React.ChangeEvent const { value } = event.target @@ -73,6 +100,12 @@ export const EmbeddingOptions = () => { setActiveEmbeddingsProvider(provider) } + const handleChangeMetric = (e: unknown): void => { + const event = e as React.ChangeEvent + const value = event.target.value + setMetric(value) + } + if (!embeddingProviders) { return (
@@ -136,6 +169,45 @@ export const EmbeddingOptions = () => {
+
+
Code snippets
+ handleRelevantCodeSnippetsChange(e)} + /> + + The number code snippets to be used as context. + +
+
+
Filepaths
+ handleRelevantFilepathsChange(e)} + /> + + The number of filepaths to be used as context. + +
+
+
Search Metric
+ + {EMBEDDING_METRICS.map((metric: string) => ( + + {metric} + + ))} + + + The metric to be used for the vector search. + +