From 8e4f943e30f4e8b1fd7521176350a469fdb51b1a Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Fri, 6 Dec 2024 01:03:43 -0800 Subject: [PATCH] move node to electron-main, leaving react stuff in contrib/ --- package-lock.json | 186 +++++++++++---- package.json | 4 +- src/vs/code/electron-main/app.ts | 11 +- .../platform/void/browser/metricsService.ts | 32 +++ src/vs/platform/void/common/configTypes.ts | 210 +++++++++++++++++ .../platform/void/common/llmMessageTypes.ts | 3 +- src/vs/platform/void/common/metricsService.ts | 10 + .../electron-main/llmMessage/anthropic.ts} | 3 +- .../void/electron-main/llmMessage/gemini.ts} | 2 +- .../electron-main/llmMessage/greptile.ts} | 2 +- .../void/electron-main/llmMessage/groq.ts} | 4 +- .../void/electron-main/llmMessage/ollama.ts} | 6 +- .../void/electron-main/llmMessage/openai.ts} | 4 +- .../llmMessage/sendLLMMessage.ts} | 16 +- .../void/electron-main/llmMessage/util.ts | 21 ++ .../void/electron-main/llmMessageChannel.ts | 17 +- .../void/electron-main/metricsMainService.ts | 52 +++++ .../react/src/sendLLMMessage/_types.tsx | 12 - .../react/src/sidebar-tsx/SidebarSettings.tsx | 4 +- .../void/browser/react/src/util/posthog.tsx | 4 - .../contrib/void/browser/registerConfig.ts | 219 +----------------- .../contrib/void/browser/registerMetrics.ts | 52 ----- .../contrib/void/browser/void.contribution.ts | 5 +- 23 files changed, 510 insertions(+), 369 deletions(-) create mode 100644 src/vs/platform/void/browser/metricsService.ts create mode 100644 src/vs/platform/void/common/configTypes.ts create mode 100644 src/vs/platform/void/common/metricsService.ts rename src/vs/{workbench/contrib/void/browser/react/src/sendLLMMessage/anthropic.tsx => platform/void/electron-main/llmMessage/anthropic.ts} (93%) rename src/vs/{workbench/contrib/void/browser/react/src/sendLLMMessage/gemini.tsx => platform/void/electron-main/llmMessage/gemini.ts} (95%) rename src/vs/{workbench/contrib/void/browser/react/src/sendLLMMessage/greptile.tsx => platform/void/electron-main/llmMessage/greptile.ts} (96%) rename src/vs/{workbench/contrib/void/browser/react/src/sendLLMMessage/groq.tsx => platform/void/electron-main/llmMessage/groq.ts} (87%) rename src/vs/{workbench/contrib/void/browser/react/src/sendLLMMessage/ollama.tsx => platform/void/electron-main/llmMessage/ollama.ts} (84%) rename src/vs/{workbench/contrib/void/browser/react/src/sendLLMMessage/openai.tsx => platform/void/electron-main/llmMessage/openai.ts} (95%) rename src/vs/{workbench/contrib/void/browser/react/src/sendLLMMessage/sendLLMMessage.tsx => platform/void/electron-main/llmMessage/sendLLMMessage.ts} (87%) create mode 100644 src/vs/platform/void/electron-main/llmMessage/util.ts create mode 100644 src/vs/platform/void/electron-main/metricsMainService.ts delete mode 100644 src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/_types.tsx delete mode 100644 src/vs/workbench/contrib/void/browser/react/src/util/posthog.tsx delete mode 100644 src/vs/workbench/contrib/void/browser/registerMetrics.ts diff --git a/package-lock.json b/package-lock.json index afc964f6..8cd1f77f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,8 @@ "@microsoft/1ds-core-js": "^3.2.13", "@microsoft/1ds-post-js": "^3.2.13", "@parcel/watcher": "2.1.0", + "@rrweb/record": "^2.0.0-alpha.17", + "@rrweb/types": "^2.0.0-alpha.17", "@vscode/deviceid": "^0.1.1", "@vscode/iconv-lite-umd": "0.7.0", "@vscode/policy-watcher": "^1.1.4", @@ -47,6 +49,7 @@ "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta21", "open": "^8.4.2", + "posthog-node": "^4.3.1", "tas-client-umd": "0.2.0", "v8-inspect-profiler": "^0.1.1", "vscode-oniguruma": "1.7.0", @@ -156,7 +159,6 @@ "path-browserify": "^1.0.1", "postcss": "^8.4.33", "postcss-nesting": "^12.0.2", - "posthog-js": "^1.184.2", "pump": "^1.0.1", "rcedit": "^1.1.0", "react": "^18.3.1", @@ -2599,6 +2601,31 @@ "win32" ] }, + "node_modules/@rrweb/record": { + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@rrweb/record/-/record-2.0.0-alpha.17.tgz", + "integrity": "sha512-Je+lzjeWMF8/I0IDoXFzkGPKT8j7AkaBup5YcwUHlkp18VhLVze416MvI6915teE27uUA2ScXMXzG0Yiu5VTIw==", + "license": "MIT", + "dependencies": { + "@rrweb/types": "^2.0.0-alpha.17", + "rrweb": "^2.0.0-alpha.17" + } + }, + "node_modules/@rrweb/types": { + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@rrweb/types/-/types-2.0.0-alpha.17.tgz", + "integrity": "sha512-AfDTVUuCyCaIG0lTSqYtrZqJX39ZEYzs4fYKnexhQ+id+kbZIpIJtaut5cto6dWZbB3SEe4fW0o90Po3LvTmfg==", + "license": "MIT", + "dependencies": { + "rrweb-snapshot": "^2.0.0-alpha.17" + } + }, + "node_modules/@rrweb/utils": { + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@rrweb/utils/-/utils-2.0.0-alpha.17.tgz", + "integrity": "sha512-HCsasPERBwOS9/LQeOytO2ETKTCqRj1wORBuxiy3t41hKhmi225DdrUPiWnyDdTQm1GdVbOymMRknJVPnZaSXw==", + "license": "MIT" + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -2972,6 +2999,12 @@ "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==", "dev": true }, + "node_modules/@types/css-font-loading-module": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz", + "integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==", + "license": "MIT" + }, "node_modules/@types/debug": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", @@ -4423,6 +4456,12 @@ } } }, + "node_modules/@xstate/fsm": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.6.5.tgz", + "integrity": "sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw==", + "license": "MIT" + }, "node_modules/@xterm/addon-clipboard": { "version": "0.2.0-beta.47", "resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.2.0-beta.47.tgz", @@ -5208,6 +5247,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/b4a": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", @@ -5316,6 +5366,15 @@ "node": ">=0.10.0" } }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -6572,18 +6631,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/core-js": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", - "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -8483,13 +8530,6 @@ } } }, - "node_modules/fflate": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", - "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", - "dev": true, - "license": "MIT" - }, "node_modules/figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -8892,6 +8932,26 @@ "util-deprecate": "~1.0.1" } }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "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", @@ -14817,6 +14877,12 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, "node_modules/mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -16579,7 +16645,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -16825,7 +16890,6 @@ "version": "8.4.48", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.48.tgz", "integrity": "sha512-GCRK8F6+Dl7xYniR5a4FYbpBzU8XnZVeowqsQFYdcXuSbChgiks7qybSkbvnaeqv0G0B+dd9/jJgH8kkLDQeEA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -17559,7 +17623,6 @@ "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, "funding": [ { "type": "github", @@ -17573,28 +17636,17 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/posthog-js": { - "version": "1.184.2", - "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.184.2.tgz", - "integrity": "sha512-n7OxFntH7m4sw/GsuUAliWGqBDV7g7IemvjwGISCQFQpf5cSqZgmvT2V2O3GHXpONiEgwL/Ud/+zWmhZbWLExg==", - "dev": true, + "node_modules/posthog-node": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-4.3.1.tgz", + "integrity": "sha512-By9SEGZxBLC7GVyVb+HlJlpxM/xI4iLUgwtsBS8f4bZ0wqYKiNHoYcFEwMJnTM9xQcQZztr6dqLmsJ7jCv0vxA==", "license": "MIT", "dependencies": { - "core-js": "^3.38.1", - "fflate": "^0.4.8", - "preact": "^10.19.3", - "web-vitals": "^4.2.0" - } - }, - "node_modules/preact": { - "version": "10.24.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", - "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" + "axios": "^1.7.4", + "rusha": "^0.8.14" + }, + "engines": { + "node": ">=15.0.0" } }, "node_modules/prebuild-install": { @@ -18676,6 +18728,40 @@ "fsevents": "~2.3.2" } }, + "node_modules/rrdom": { + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/rrdom/-/rrdom-2.0.0-alpha.17.tgz", + "integrity": "sha512-b6caDiNcFO96Opp7TGdcVd4OLGSXu5dJe+A0IDiAu8mk7OmhqZCSDlgQdTKmdO5wMf4zPsUTgb8H/aNvR3kDHA==", + "license": "MIT", + "dependencies": { + "rrweb-snapshot": "^2.0.0-alpha.17" + } + }, + "node_modules/rrweb": { + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/rrweb/-/rrweb-2.0.0-alpha.17.tgz", + "integrity": "sha512-GQxBkCC4r9XL2bwSdv7iIS49M3cEA8OtObVq0rrQ4GUT4+h7omucGQ4x7m5YN5Vq1oalStBaBlYqF7yRnfG3JA==", + "license": "MIT", + "dependencies": { + "@rrweb/types": "^2.0.0-alpha.17", + "@rrweb/utils": "^2.0.0-alpha.17", + "@types/css-font-loading-module": "0.0.7", + "@xstate/fsm": "^1.4.0", + "base64-arraybuffer": "^1.0.1", + "mitt": "^3.0.0", + "rrdom": "^2.0.0-alpha.17", + "rrweb-snapshot": "^2.0.0-alpha.17" + } + }, + "node_modules/rrweb-snapshot": { + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/rrweb-snapshot/-/rrweb-snapshot-2.0.0-alpha.17.tgz", + "integrity": "sha512-GBg5pV8LHOTbeVmH2VHLEFR0mc2QpQMzAvcoxEGfPNWgWHc8UvKCyq7pqN1vA+fDZ+yXXbixeO0kB2pzVvFCBw==", + "license": "MIT", + "dependencies": { + "postcss": "^8.4.38" + } + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -18705,6 +18791,12 @@ } ] }, + "node_modules/rusha": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", + "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==", + "license": "MIT" + }, "node_modules/rxjs": { "version": "6.6.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", @@ -19603,7 +19695,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -22287,13 +22378,6 @@ "integrity": "sha512-weOVgZ3aAARgdnb220GqYuh7+rZU0Ka9k9yfKtGAzEYMa6GgiCzW9JjQRJyCJakvibQW+dfjJdihjInKuuCAUQ==", "dev": true }, - "node_modules/web-vitals": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", - "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index 968a9b1d..8f4f7878 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,8 @@ "@microsoft/1ds-core-js": "^3.2.13", "@microsoft/1ds-post-js": "^3.2.13", "@parcel/watcher": "2.1.0", + "@rrweb/record": "^2.0.0-alpha.17", + "@rrweb/types": "^2.0.0-alpha.17", "@vscode/deviceid": "^0.1.1", "@vscode/iconv-lite-umd": "0.7.0", "@vscode/policy-watcher": "^1.1.4", @@ -109,6 +111,7 @@ "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta21", "open": "^8.4.2", + "posthog-node": "^4.3.1", "tas-client-umd": "0.2.0", "v8-inspect-profiler": "^0.1.1", "vscode-oniguruma": "1.7.0", @@ -218,7 +221,6 @@ "path-browserify": "^1.0.1", "postcss": "^8.4.33", "postcss-nesting": "^12.0.2", - "posthog-js": "^1.184.2", "pump": "^1.0.1", "rcedit": "^1.1.0", "react": "^18.3.1", diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 59e8af61..2cd9bffa 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -122,6 +122,8 @@ import { ICSSDevelopmentService, CSSDevelopmentService } from '../../platform/cs import { ExtensionSignatureVerificationService, IExtensionSignatureVerificationService } from '../../platform/extensionManagement/node/extensionSignatureVerificationService.js'; import { LLMMessageChannel } from '../../platform/void/electron-main/llmMessageChannel.js'; +import { IMetricsService } from '../../platform/void/common/metricsService.js'; +import { MetricsMainService } from '../../platform/void/electron-main/metricsMainService.js'; /** * The main VS Code application. There will only ever be one instance, @@ -1103,6 +1105,9 @@ export class CodeApplication extends Disposable { services.set(ITelemetryService, NullTelemetryService); } + // Void main process services (required for services with a channel for comm between browser and electron-main (node)) + services.set(IMetricsService, new SyncDescriptor(MetricsMainService, undefined, false)); + // Default Extensions Profile Init services.set(IExtensionsProfileScannerService, new SyncDescriptor(ExtensionsProfileScannerService, undefined, true)); services.set(IExtensionsScannerService, new SyncDescriptor(ExtensionsScannerService, undefined, true)); @@ -1238,8 +1243,10 @@ export class CodeApplication extends Disposable { sharedProcessClient.then(client => client.registerChannel('logger', loggerChannel)); // Void - // const sendLLMMessageChannel = ProxyChannel.fromService(accessor.get(ISendLLMMessageService), disposables); - const sendLLMMessageChannel = new LLMMessageChannel(); + const metricsChannel = ProxyChannel.fromService(accessor.get(IMetricsService), disposables); + mainProcessElectronServer.registerChannel('void-channel-metrics', metricsChannel); + + const sendLLMMessageChannel = new LLMMessageChannel(accessor.get(IMetricsService)); mainProcessElectronServer.registerChannel('void-channel-sendLLMMessage', sendLLMMessageChannel); // Extension Host Debug Broadcasting diff --git a/src/vs/platform/void/browser/metricsService.ts b/src/vs/platform/void/browser/metricsService.ts new file mode 100644 index 00000000..dfd7c898 --- /dev/null +++ b/src/vs/platform/void/browser/metricsService.ts @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Glass Devtools, Inc. All rights reserved. + * Void Editor additions licensed under the AGPLv3 License. + *--------------------------------------------------------------------------------------------*/ + +import { IChannel } from '../../../base/parts/ipc/common/ipc.js'; +import { IMainProcessService } from '../../ipc/common/mainProcessService.js'; +import { InstantiationType, registerSingleton } from '../../instantiation/common/extensions.js'; +import { IMetricsService } from '../common/metricsService.js'; + +// BROWSER IMPLEMENTATION, calls channel + +export class MetricsService implements IMetricsService { + + readonly _serviceBrand: undefined; + private readonly channel: IChannel; + + constructor( + @IMainProcessService mainProcessService: IMainProcessService // (only usable on client side) + ) { + this.channel = mainProcessService.getChannel('void-channel-metrics') + } + + // call capture on the channel + capture(...params: Parameters) { + this.channel.call('capture', params); + } + +} + +registerSingleton(IMetricsService, MetricsService, InstantiationType.Eager); + diff --git a/src/vs/platform/void/common/configTypes.ts b/src/vs/platform/void/common/configTypes.ts new file mode 100644 index 00000000..b6d27138 --- /dev/null +++ b/src/vs/platform/void/common/configTypes.ts @@ -0,0 +1,210 @@ + +const configEnum = (description: string, defaultVal: EnumArr[number], enumArr: EnumArr) => { + return { + description, + defaultVal, + enumArr, + } +} + +const configString = (description: string, defaultVal: string) => { + return { + description, + defaultVal, + enumArr: undefined, + } +} + + +// fields you can customize (don't forget 'default' - it isn't included here!) +export const nonDefaultConfigFields = [ + 'anthropic', + 'openAI', + 'gemini', + 'greptile', + 'groq', + 'ollama', + 'openRouter', + 'openAICompatible', + 'azure', +] as const + + + +export const voidConfigInfo: Record< + typeof nonDefaultConfigFields[number] | 'default', { + [prop: string]: { + description: string; + enumArr?: readonly string[] | undefined; + defaultVal: string; + }; + } +> = { + default: { + whichApi: configEnum( + 'API Provider.', + 'anthropic', + nonDefaultConfigFields, + ), + + maxTokens: configEnum( + 'Max number of tokens to output.', + '1024', + [ + 'default', // this will be parseInt'd into NaN and ignored by the API. Anything that's not a number has this behavior. + '1024', + '2048', + '4096', + '8192' + ] as const, + ), + + }, + anthropic: { + apikey: configString('Anthropic API key.', ''), + model: configEnum( + 'Anthropic model to use.', + 'claude-3-5-sonnet-20240620', + [ + 'claude-3-5-sonnet-20240620', + 'claude-3-opus-20240229', + 'claude-3-sonnet-20240229', + 'claude-3-haiku-20240307' + ] as const, + ), + }, + openAI: { + apikey: configString('OpenAI API key.', ''), + model: configEnum( + 'OpenAI model to use.', + 'gpt-4o', + [ + 'o1-preview', + 'o1-mini', + 'gpt-4o', + 'gpt-4o-2024-05-13', + 'gpt-4o-2024-08-06', + 'gpt-4o-mini', + 'gpt-4o-mini-2024-07-18', + 'gpt-4-turbo', + 'gpt-4-turbo-2024-04-09', + 'gpt-4-turbo-preview', + 'gpt-4-0125-preview', + 'gpt-4-1106-preview', + 'gpt-4', + 'gpt-4-0613', + 'gpt-3.5-turbo-0125', + 'gpt-3.5-turbo', + 'gpt-3.5-turbo-1106' + ] as const + ), + }, + greptile: { + apikey: configString('Greptile API key.', ''), + githubPAT: configString('Github PAT that Greptile uses to access your repository', ''), + remote: configEnum( + 'Repo location', + 'github', + [ + 'github', + 'gitlab' + ] as const + ), + repository: configString('Repository identifier in "owner / repository" format.', ''), + branch: configString('Name of the branch to use.', 'main'), + }, + groq: { + apikey: configString('Groq API key.', ''), + model: configEnum( + 'Groq model to use.', + 'mixtral-8x7b-32768', + [ + "mixtral-8x7b-32768", + "llama2-70b-4096", + "gemma-7b-it" + ] as const + ), + }, + ollama: { + endpoint: configString( + 'The endpoint of your Ollama instance. Start Ollama by running `OLLAMA_ORIGINS="vscode - webview://*" ollama serve`.', + 'http://127.0.0.1:11434' + ), + model: configEnum( + 'Ollama model to use.', + 'codestral', + ['codestral', 'qwen2.5-coder', 'qwen2.5-coder:0.5b', 'qwen2.5-coder:1.5b', 'qwen2.5-coder:3b', 'qwen2.5-coder:7b', 'qwen2.5-coder:14b', 'qwen2.5-coder:32b', 'codegemma', 'codegemma:2b', 'codegemma:7b', 'codellama', 'codellama:7b', 'codellama:13b', 'codellama:34b', 'codellama:70b', 'codellama:code', 'codellama:python', 'command-r', 'command-r:35b', 'command-r-plus', 'command-r-plus:104b', 'deepseek-coder-v2', 'deepseek-coder-v2:16b', 'deepseek-coder-v2:236b', 'falcon2', 'falcon2:11b', 'firefunction-v2', 'firefunction-v2:70b', 'gemma', 'gemma:2b', 'gemma:7b', 'gemma2', 'gemma2:2b', 'gemma2:9b', 'gemma2:27b', 'llama2', 'llama2:7b', 'llama2:13b', 'llama2:70b', 'llama3', 'llama3:8b', 'llama3:70b', 'llama3-chatqa', 'llama3-chatqa:8b', 'llama3-chatqa:70b', 'llama3-gradient', 'llama3-gradient:8b', 'llama3-gradient:70b', 'llama3.1', 'llama3.1:8b', 'llama3.1:70b', 'llama3.1:405b', 'llava', 'llava:7b', 'llava:13b', 'llava:34b', 'llava-llama3', 'llava-llama3:8b', 'llava-phi3', 'llava-phi3:3.8b', 'mistral', 'mistral:7b', 'mistral-large', 'mistral-large:123b', 'mistral-nemo', 'mistral-nemo:12b', 'mixtral', 'mixtral:8x7b', 'mixtral:8x22b', 'moondream', 'moondream:1.8b', 'openhermes', 'openhermes:v2.5', 'phi3', 'phi3:3.8b', 'phi3:14b', 'phi3.5', 'phi3.5:3.8b', 'qwen', 'qwen:7b', 'qwen:14b', 'qwen:32b', 'qwen:72b', 'qwen:110b', 'qwen2', 'qwen2:0.5b', 'qwen2:1.5b', 'qwen2:7b', 'qwen2:72b', 'smollm', 'smollm:135m', 'smollm:360m', 'smollm:1.7b'] as const + ), + }, + openRouter: { + model: configString( + 'OpenRouter model to use.', + 'openai/gpt-4o' + ), + apikey: configString('OpenRouter API key.', ''), + }, + openAICompatible: { + endpoint: configString('The baseUrl (exluding /chat/completions).', 'http://127.0.0.1:11434/v1'), + model: configString('The name of the model to use.', 'gpt-4o'), + apikey: configString('Your API key.', ''), + }, + azure: { + // 'void.azure.apiKey': { + // 'type': 'string', + // 'description': 'Azure API key.' + // }, + // 'void.azure.deploymentId': { + // 'type': 'string', + // 'description': 'Azure API deployment ID.' + // }, + // 'void.azure.resourceName': { + // 'type': 'string', + // 'description': 'Name of the Azure OpenAI resource. Either this or `baseURL` can be used. \nThe resource name is used in the assembled URL: `https://{resourceName}.openai.azure.com/openai/deployments/{modelId}{path}`' + // }, + // 'void.azure.providerSettings': { + // 'type': 'object', + // 'properties': { + // 'baseURL': { + // 'type': 'string', + // 'default': 'https://${resourceName}.openai.azure.com/openai/deployments', + // 'description': 'Azure API base URL.' + // }, + // 'headers': { + // 'type': 'object', + // 'description': 'Custom headers to include in the requests.' + // } + // } + // }, + }, + gemini: { + apikey: configString('Google API key.', ''), + model: configEnum( + 'Gemini model to use.', + 'gemini-1.5-flash', + [ + 'gemini-1.5-flash', + 'gemini-1.5-pro', + 'gemini-1.5-flash-8b', + 'gemini-1.0-pro' + ] as const + ), + }, +} + + +// this is the type that comes with metadata like desc, default val, etc +export type VoidConfigInfo = typeof voidConfigInfo +export type VoidConfigField = keyof typeof voidConfigInfo // typeof configFields[number] + +// this is the type that specifies the user's actual config +export type PartialVoidConfig = { + [K in keyof typeof voidConfigInfo]?: { + [P in keyof typeof voidConfigInfo[K]]?: typeof voidConfigInfo[K][P]['defaultVal'] + } +} + +export type VoidConfig = { + [K in keyof typeof voidConfigInfo]: { + [P in keyof typeof voidConfigInfo[K]]: typeof voidConfigInfo[K][P]['defaultVal'] + } +} diff --git a/src/vs/platform/void/common/llmMessageTypes.ts b/src/vs/platform/void/common/llmMessageTypes.ts index 28733511..651fef0c 100644 --- a/src/vs/platform/void/common/llmMessageTypes.ts +++ b/src/vs/platform/void/common/llmMessageTypes.ts @@ -3,7 +3,8 @@ * Void Editor additions licensed under the AGPLv3 License. *--------------------------------------------------------------------------------------------*/ -import { VoidConfig } from '../../../workbench/contrib/void/browser/registerConfig.js'; +import { VoidConfig } from './configTypes.js' + // ---------- type definitions ---------- diff --git a/src/vs/platform/void/common/metricsService.ts b/src/vs/platform/void/common/metricsService.ts new file mode 100644 index 00000000..2459214e --- /dev/null +++ b/src/vs/platform/void/common/metricsService.ts @@ -0,0 +1,10 @@ +import { createDecorator } from '../../instantiation/common/instantiation.js'; + +export interface IMetricsService { + readonly _serviceBrand: undefined; + capture(event: string, params: Record): void; +} + +export const IMetricsService = createDecorator('metricsService'); + + diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/anthropic.tsx b/src/vs/platform/void/electron-main/llmMessage/anthropic.ts similarity index 93% rename from src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/anthropic.tsx rename to src/vs/platform/void/electron-main/llmMessage/anthropic.ts index 36fa78ac..50990537 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/anthropic.tsx +++ b/src/vs/platform/void/electron-main/llmMessage/anthropic.ts @@ -1,6 +1,5 @@ import Anthropic from '@anthropic-ai/sdk'; -import { SendLLMMessageFnTypeInternal } from './_types.js'; -import { parseMaxTokensStr } from '../../../registerConfig.js'; +import { parseMaxTokensStr, SendLLMMessageFnTypeInternal } from './util.js'; // Anthropic type LLMMessageAnthropic = { diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/gemini.tsx b/src/vs/platform/void/electron-main/llmMessage/gemini.ts similarity index 95% rename from src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/gemini.tsx rename to src/vs/platform/void/electron-main/llmMessage/gemini.ts index 5a883177..f13cf9f8 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/gemini.tsx +++ b/src/vs/platform/void/electron-main/llmMessage/gemini.ts @@ -1,5 +1,5 @@ import { Content, GoogleGenerativeAI, GoogleGenerativeAIFetchError } from '@google/generative-ai'; -import { SendLLMMessageFnTypeInternal } from './_types.js'; +import { SendLLMMessageFnTypeInternal } from './util'; // Gemini export const sendGeminiMsg: SendLLMMessageFnTypeInternal = async ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => { diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/greptile.tsx b/src/vs/platform/void/electron-main/llmMessage/greptile.ts similarity index 96% rename from src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/greptile.tsx rename to src/vs/platform/void/electron-main/llmMessage/greptile.ts index eb7b4596..4ee108d6 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/greptile.tsx +++ b/src/vs/platform/void/electron-main/llmMessage/greptile.ts @@ -3,7 +3,7 @@ // https://docs.greptile.com/api-reference/query // https://docs.greptile.com/quickstart#sample-response-streamed -import { SendLLMMessageFnTypeInternal } from './_types.js'; +import { SendLLMMessageFnTypeInternal } from './util'; export const sendGreptileMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => { diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/groq.tsx b/src/vs/platform/void/electron-main/llmMessage/groq.ts similarity index 87% rename from src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/groq.tsx rename to src/vs/platform/void/electron-main/llmMessage/groq.ts index dd9de3e1..9b2b343a 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/groq.tsx +++ b/src/vs/platform/void/electron-main/llmMessage/groq.ts @@ -1,6 +1,6 @@ import Groq from 'groq-sdk'; -import { SendLLMMessageFnTypeInternal } from './_types.js'; -import { parseMaxTokensStr } from '../../../registerConfig.js'; +import { SendLLMMessageFnTypeInternal } from './util'; +import { parseMaxTokensStr } from './util.js'; // Groq export const sendGroqMsg: SendLLMMessageFnTypeInternal = async ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => { diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/ollama.tsx b/src/vs/platform/void/electron-main/llmMessage/ollama.ts similarity index 84% rename from src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/ollama.tsx rename to src/vs/platform/void/electron-main/llmMessage/ollama.ts index 399065cb..7b41da01 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/ollama.tsx +++ b/src/vs/platform/void/electron-main/llmMessage/ollama.ts @@ -1,6 +1,6 @@ -import { Ollama, ErrorResponse } from 'ollama/browser'; -import { parseMaxTokensStr } from '../../../registerConfig.js'; -import { SendLLMMessageFnTypeInternal } from './_types.js'; +import { Ollama, ErrorResponse } from 'ollama'; +import { SendLLMMessageFnTypeInternal } from './util'; +import { parseMaxTokensStr } from './util.js'; // Ollama export const sendOllamaMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => { diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/openai.tsx b/src/vs/platform/void/electron-main/llmMessage/openai.ts similarity index 95% rename from src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/openai.tsx rename to src/vs/platform/void/electron-main/llmMessage/openai.ts index 78d6671a..7d96792e 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/openai.tsx +++ b/src/vs/platform/void/electron-main/llmMessage/openai.ts @@ -1,6 +1,6 @@ import OpenAI from 'openai'; -import { parseMaxTokensStr } from '../../../registerConfig.js'; -import { SendLLMMessageFnTypeInternal } from './_types.js'; +import { SendLLMMessageFnTypeInternal } from './util'; +import { parseMaxTokensStr } from './util.js'; // OpenAI, OpenRouter, OpenAICompatible diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/sendLLMMessage.tsx b/src/vs/platform/void/electron-main/llmMessage/sendLLMMessage.ts similarity index 87% rename from src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/sendLLMMessage.tsx rename to src/vs/platform/void/electron-main/llmMessage/sendLLMMessage.ts index d7872ddf..51fedd7e 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/sendLLMMessage.tsx +++ b/src/vs/platform/void/electron-main/llmMessage/sendLLMMessage.ts @@ -1,5 +1,6 @@ -import { posthog } from 'posthog-js' -import type { OnText, OnError, OnFinalMessage, SendLLMMMessageParams, } from '../../../../../../../platform/void/common/llmMessageTypes.js'; +import { SendLLMMMessageParams, OnText, OnFinalMessage, OnError } from '../../common/llmMessageTypes.js'; +import { IMetricsService } from '../../common/metricsService.js'; + import { sendAnthropicMsg } from './anthropic.js'; import { sendGeminiMsg } from './gemini.js'; import { sendGreptileMsg } from './greptile.js'; @@ -8,7 +9,14 @@ import { sendOllamaMsg } from './ollama.js'; import { sendOpenAIMsg } from './openai.js'; -export const sendLLMMessage = ({ messages, onText: onText_, onFinalMessage: onFinalMessage_, onError: onError_, abortRef: abortRef_, voidConfig, logging: { loggingName } }: SendLLMMMessageParams) => { +export const sendLLMMessage = ( + { + messages, onText: onText_, onFinalMessage: onFinalMessage_, onError: onError_, + abortRef: abortRef_, voidConfig, logging: { loggingName }, + }: SendLLMMMessageParams, + + metricsService: IMetricsService +) => { if (!voidConfig) return; // trim message content (Anthropic and other providers give an error if there is trailing whitespace) @@ -16,7 +24,7 @@ export const sendLLMMessage = ({ messages, onText: onText_, onFinalMessage: onFi // only captures number of messages and message "shape", no actual code, instructions, prompts, etc const captureChatEvent = (eventId: string, extras?: object) => { - posthog.capture(eventId, { + metricsService.capture(eventId, { whichApi: voidConfig.default['whichApi'], numMessages: messages?.length, messagesShape: messages?.map(msg => ({ role: msg.role, length: msg.content.length })), diff --git a/src/vs/platform/void/electron-main/llmMessage/util.ts b/src/vs/platform/void/electron-main/llmMessage/util.ts new file mode 100644 index 00000000..92c71156 --- /dev/null +++ b/src/vs/platform/void/electron-main/llmMessage/util.ts @@ -0,0 +1,21 @@ +import { VoidConfig } from '../../common/configTypes' +import { LLMMessage, OnText, OnFinalMessage, OnError } from '../../common/llmMessageTypes' + +export const parseMaxTokensStr = (maxTokensStr: string) => { + // parse the string but only if the full string is a valid number, eg parseInt('100abc') should return NaN + const int = isNaN(Number(maxTokensStr)) ? undefined : parseInt(maxTokensStr) + if (Number.isNaN(int)) + return undefined + return int +} + + +export type SendLLMMessageFnTypeInternal = (params: { + messages: LLMMessage[]; + onText: OnText; + onFinalMessage: OnFinalMessage; + onError: OnError; + voidConfig: VoidConfig; + + _setAborter: (aborter: () => void) => void; +}) => void diff --git a/src/vs/platform/void/electron-main/llmMessageChannel.ts b/src/vs/platform/void/electron-main/llmMessageChannel.ts index dd437286..f4646f8b 100644 --- a/src/vs/platform/void/electron-main/llmMessageChannel.ts +++ b/src/vs/platform/void/electron-main/llmMessageChannel.ts @@ -3,17 +3,16 @@ * Void Editor additions licensed under the AGPLv3 License. *--------------------------------------------------------------------------------------------*/ -// this channel is registered in `app.ts` -// code convention is to make a service responsible for this stuff, and not a channel, but this is simpler. -// you could create one instance in electron-main/my-service.ts and one in browser/my-service.ts (and define the interface IMyService in common/my-service.ts), but we just use a channel here -// registerSingleton(ISendLLMMessageService, SendLLMMessageService, InstantiationType.Delayed); +// registered in app.ts +// code convention is to make a service responsible for this stuff, and not a channel, but having fewer files is simpler... import { IServerChannel } from '../../../base/parts/ipc/common/ipc.js'; import { Emitter, Event } from '../../../base/common/event.js'; -import { sendLLMMessage } from '../../../workbench/contrib/void/browser/react/out/sendLLMMessage/sendLLMMessage.js'; import { listenerNames, ProxyOnTextPayload, ProxyOnErrorPayload, ProxyOnFinalMessagePayload, ProxyLLMMessageParams, AbortRef, SendLLMMMessageParams, ProxyLLMMessageAbortParams } from '../common/llmMessageTypes.js'; +import { sendLLMMessage } from './llmMessage/sendLLMMessage.js' +import { IMetricsService } from '../common/metricsService.js'; -// NODE IMPLEMENTATION OF SENDLLMMESSAGE - calls sendLLMMessage() and returns listeners +// NODE IMPLEMENTATION - calls actual sendLLMMessage() and returns listeners to it export class LLMMessageChannel implements IServerChannel { private readonly _onText = new Emitter(); @@ -29,7 +28,9 @@ export class LLMMessageChannel implements IServerChannel { private readonly _abortRefOfRequestId: Record = {} - constructor() { } + constructor( + private readonly metricsService: IMetricsService + ) { } // browser uses this to listen for changes listen(_: unknown, event: typeof listenerNames[number]): Event { @@ -80,7 +81,7 @@ export class LLMMessageChannel implements IServerChannel { onError: ({ error }) => { this._onError.fire({ requestId, error }); }, abortRef: this._abortRefOfRequestId[requestId], } - sendLLMMessage(mainThreadParams); + sendLLMMessage(mainThreadParams, this.metricsService); } private _callAbort(params: ProxyLLMMessageAbortParams) { diff --git a/src/vs/platform/void/electron-main/metricsMainService.ts b/src/vs/platform/void/electron-main/metricsMainService.ts new file mode 100644 index 00000000..42849bef --- /dev/null +++ b/src/vs/platform/void/electron-main/metricsMainService.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Glass Devtools, Inc. All rights reserved. + * Void Editor additions licensed under the AGPLv3 License. + *--------------------------------------------------------------------------------------------*/ + +import { Disposable } from '../../../base/common/lifecycle.js'; +import { ITelemetryService } from '../../telemetry/common/telemetry.js'; + +import { IMetricsService } from '../common/metricsService.js'; +import { PostHog } from 'posthog-node' + + +// posthog.init('phc_UanIdujHiLp55BkUTjB1AuBXcasVkdqRwgnwRlWESH2', { api_host: 'https://us.i.posthog.com', }) + +// const buildEnv = 'development'; +// const buildNumber = '1.0.0'; +// const isMac = process.platform === 'darwin'; +// // TODO use commandKey +// const commandKey = isMac ? '⌘' : 'Ctrl'; +// const systemInfo = { +// buildEnv, +// buildNumber, +// isMac, +// } + +export class MetricsMainService extends Disposable implements IMetricsService { + _serviceBrand: undefined; + + readonly _distinctId: string + readonly client: PostHog + + constructor( + @ITelemetryService private readonly _telemetryService: ITelemetryService + ) { + super() + this.client = new PostHog('phc_UanIdujHiLp55BkUTjB1AuBXcasVkdqRwgnwRlWESH2', { host: 'https://us.i.posthog.com', }) + + const { devDeviceId, firstSessionDate, machineId } = this._telemetryService + this._distinctId = devDeviceId + this.client.identify({ distinctId: devDeviceId, properties: { firstSessionDate, machineId } }) + + console.log('Void posthog metrics info:', JSON.stringify({ devDeviceId, firstSessionDate, machineId })) + } + + capture: IMetricsService['capture'] = (event, params) => { + console.log('Capturing', { event, params }) + console.log('full capture:', { distinctId: this._distinctId, event, properties: params }) + this.client.capture({ distinctId: this._distinctId, event, properties: params }) + } +} + + diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/_types.tsx b/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/_types.tsx deleted file mode 100644 index 6076cdac..00000000 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/_types.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { LLMMessage, OnError, OnFinalMessage, OnText } from '../../../../../../../platform/void/common/llmMessageTypes.js'; -import { VoidConfig } from '../../../registerConfig.js'; - -export type SendLLMMessageFnTypeInternal = (params: { - messages: LLMMessage[]; - onText: OnText; - onFinalMessage: OnFinalMessage; - onError: OnError; - voidConfig: VoidConfig; - - _setAborter: (aborter: () => void) => void; -}) => void diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarSettings.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarSettings.tsx index ec951478..0dadf12b 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarSettings.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarSettings.tsx @@ -4,10 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useConfigState, useService } from '../util/services.js'; -import { IVoidConfigStateService, nonDefaultConfigFields, PartialVoidConfig, VoidConfig, VoidConfigField, VoidConfigInfo, SetFieldFnType, ConfigState } from '../../../registerConfig.js'; + import { VoidSelectBox, VoidInputBox } from './inputs.js'; import { HistoryInputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js'; import { SelectBox } from '../../../../../../../base/browser/ui/selectBox/selectBox.js'; +import { ConfigState, IVoidConfigStateService } from '../../../registerConfig.js'; +import { nonDefaultConfigFields, VoidConfigField } from '../../../../../../../platform/void/common/configTypes.js'; const SettingOfFieldAndParam = ({ field, param, configState, configStateService }: diff --git a/src/vs/workbench/contrib/void/browser/react/src/util/posthog.tsx b/src/vs/workbench/contrib/void/browser/react/src/util/posthog.tsx deleted file mode 100644 index 738f6799..00000000 --- a/src/vs/workbench/contrib/void/browser/react/src/util/posthog.tsx +++ /dev/null @@ -1,4 +0,0 @@ - -import posthog from 'posthog-js'; - -export { posthog } diff --git a/src/vs/workbench/contrib/void/browser/registerConfig.ts b/src/vs/workbench/contrib/void/browser/registerConfig.ts index 46fc122f..74826458 100644 --- a/src/vs/workbench/contrib/void/browser/registerConfig.ts +++ b/src/vs/workbench/contrib/void/browser/registerConfig.ts @@ -9,224 +9,7 @@ import { IEncryptionService } from '../../../../platform/encryption/common/encry import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js'; import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js'; import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js'; - -const configEnum = (description: string, defaultVal: EnumArr[number], enumArr: EnumArr) => { - return { - description, - defaultVal, - enumArr, - } -} - -const configString = (description: string, defaultVal: string) => { - return { - description, - defaultVal, - enumArr: undefined, - } -} - -export const parseMaxTokensStr = (maxTokensStr: string) => { - // parse the string but only if the full string is a valid number, eg parseInt('100abc') should return NaN - const int = isNaN(Number(maxTokensStr)) ? undefined : parseInt(maxTokensStr) - if (Number.isNaN(int)) - return undefined - return int -} - - -// fields you can customize (don't forget 'default' - it isn't included here!) -export const nonDefaultConfigFields = [ - 'anthropic', - 'openAI', - 'gemini', - 'greptile', - 'groq', - 'ollama', - 'openRouter', - 'openAICompatible', - 'azure', -] as const - - - -const voidConfigInfo: Record< - typeof nonDefaultConfigFields[number] | 'default', { - [prop: string]: { - description: string; - enumArr?: readonly string[] | undefined; - defaultVal: string; - }; - } -> = { - default: { - whichApi: configEnum( - 'API Provider.', - 'anthropic', - nonDefaultConfigFields, - ), - - maxTokens: configEnum( - 'Max number of tokens to output.', - '1024', - [ - 'default', // this will be parseInt'd into NaN and ignored by the API. Anything that's not a number has this behavior. - '1024', - '2048', - '4096', - '8192' - ] as const, - ), - - }, - anthropic: { - apikey: configString('Anthropic API key.', ''), - model: configEnum( - 'Anthropic model to use.', - 'claude-3-5-sonnet-20240620', - [ - 'claude-3-5-sonnet-20240620', - 'claude-3-opus-20240229', - 'claude-3-sonnet-20240229', - 'claude-3-haiku-20240307' - ] as const, - ), - }, - openAI: { - apikey: configString('OpenAI API key.', ''), - model: configEnum( - 'OpenAI model to use.', - 'gpt-4o', - [ - 'o1-preview', - 'o1-mini', - 'gpt-4o', - 'gpt-4o-2024-05-13', - 'gpt-4o-2024-08-06', - 'gpt-4o-mini', - 'gpt-4o-mini-2024-07-18', - 'gpt-4-turbo', - 'gpt-4-turbo-2024-04-09', - 'gpt-4-turbo-preview', - 'gpt-4-0125-preview', - 'gpt-4-1106-preview', - 'gpt-4', - 'gpt-4-0613', - 'gpt-3.5-turbo-0125', - 'gpt-3.5-turbo', - 'gpt-3.5-turbo-1106' - ] as const - ), - }, - greptile: { - apikey: configString('Greptile API key.', ''), - githubPAT: configString('Github PAT that Greptile uses to access your repository', ''), - remote: configEnum( - 'Repo location', - 'github', - [ - 'github', - 'gitlab' - ] as const - ), - repository: configString('Repository identifier in "owner / repository" format.', ''), - branch: configString('Name of the branch to use.', 'main'), - }, - groq: { - apikey: configString('Groq API key.', ''), - model: configEnum( - 'Groq model to use.', - 'mixtral-8x7b-32768', - [ - "mixtral-8x7b-32768", - "llama2-70b-4096", - "gemma-7b-it" - ] as const - ), - }, - ollama: { - endpoint: configString( - 'The endpoint of your Ollama instance. Start Ollama by running `OLLAMA_ORIGINS="vscode - webview://*" ollama serve`.', - 'http://127.0.0.1:11434' - ), - model: configEnum( - 'Ollama model to use.', - 'codestral', - ['codestral', 'qwen2.5-coder', 'qwen2.5-coder:0.5b', 'qwen2.5-coder:1.5b', 'qwen2.5-coder:3b', 'qwen2.5-coder:7b', 'qwen2.5-coder:14b', 'qwen2.5-coder:32b', 'codegemma', 'codegemma:2b', 'codegemma:7b', 'codellama', 'codellama:7b', 'codellama:13b', 'codellama:34b', 'codellama:70b', 'codellama:code', 'codellama:python', 'command-r', 'command-r:35b', 'command-r-plus', 'command-r-plus:104b', 'deepseek-coder-v2', 'deepseek-coder-v2:16b', 'deepseek-coder-v2:236b', 'falcon2', 'falcon2:11b', 'firefunction-v2', 'firefunction-v2:70b', 'gemma', 'gemma:2b', 'gemma:7b', 'gemma2', 'gemma2:2b', 'gemma2:9b', 'gemma2:27b', 'llama2', 'llama2:7b', 'llama2:13b', 'llama2:70b', 'llama3', 'llama3:8b', 'llama3:70b', 'llama3-chatqa', 'llama3-chatqa:8b', 'llama3-chatqa:70b', 'llama3-gradient', 'llama3-gradient:8b', 'llama3-gradient:70b', 'llama3.1', 'llama3.1:8b', 'llama3.1:70b', 'llama3.1:405b', 'llava', 'llava:7b', 'llava:13b', 'llava:34b', 'llava-llama3', 'llava-llama3:8b', 'llava-phi3', 'llava-phi3:3.8b', 'mistral', 'mistral:7b', 'mistral-large', 'mistral-large:123b', 'mistral-nemo', 'mistral-nemo:12b', 'mixtral', 'mixtral:8x7b', 'mixtral:8x22b', 'moondream', 'moondream:1.8b', 'openhermes', 'openhermes:v2.5', 'phi3', 'phi3:3.8b', 'phi3:14b', 'phi3.5', 'phi3.5:3.8b', 'qwen', 'qwen:7b', 'qwen:14b', 'qwen:32b', 'qwen:72b', 'qwen:110b', 'qwen2', 'qwen2:0.5b', 'qwen2:1.5b', 'qwen2:7b', 'qwen2:72b', 'smollm', 'smollm:135m', 'smollm:360m', 'smollm:1.7b'] as const - ), - }, - openRouter: { - model: configString( - 'OpenRouter model to use.', - 'openai/gpt-4o' - ), - apikey: configString('OpenRouter API key.', ''), - }, - openAICompatible: { - endpoint: configString('The baseUrl (exluding /chat/completions).', 'http://127.0.0.1:11434/v1'), - model: configString('The name of the model to use.', 'gpt-4o'), - apikey: configString('Your API key.', ''), - }, - azure: { - // 'void.azure.apiKey': { - // 'type': 'string', - // 'description': 'Azure API key.' - // }, - // 'void.azure.deploymentId': { - // 'type': 'string', - // 'description': 'Azure API deployment ID.' - // }, - // 'void.azure.resourceName': { - // 'type': 'string', - // 'description': 'Name of the Azure OpenAI resource. Either this or `baseURL` can be used. \nThe resource name is used in the assembled URL: `https://{resourceName}.openai.azure.com/openai/deployments/{modelId}{path}`' - // }, - // 'void.azure.providerSettings': { - // 'type': 'object', - // 'properties': { - // 'baseURL': { - // 'type': 'string', - // 'default': 'https://${resourceName}.openai.azure.com/openai/deployments', - // 'description': 'Azure API base URL.' - // }, - // 'headers': { - // 'type': 'object', - // 'description': 'Custom headers to include in the requests.' - // } - // } - // }, - }, - gemini: { - apikey: configString('Google API key.', ''), - model: configEnum( - 'Gemini model to use.', - 'gemini-1.5-flash', - [ - 'gemini-1.5-flash', - 'gemini-1.5-pro', - 'gemini-1.5-flash-8b', - 'gemini-1.0-pro' - ] as const - ), - }, -} - - -// this is the type that comes with metadata like desc, default val, etc -export type VoidConfigInfo = typeof voidConfigInfo -export type VoidConfigField = keyof typeof voidConfigInfo // typeof configFields[number] - -// this is the type that specifies the user's actual config -export type PartialVoidConfig = { - [K in keyof typeof voidConfigInfo]?: { - [P in keyof typeof voidConfigInfo[K]]?: typeof voidConfigInfo[K][P]['defaultVal'] - } -} - -export type VoidConfig = { - [K in keyof typeof voidConfigInfo]: { - [P in keyof typeof voidConfigInfo[K]]: typeof voidConfigInfo[K][P]['defaultVal'] - } -} +import { PartialVoidConfig, VoidConfig, nonDefaultConfigFields, voidConfigInfo, VoidConfigField, VoidConfigInfo } from '../../../../platform/void/common/configTypes.js'; const getVoidConfig = (partialVoidConfig: PartialVoidConfig): VoidConfig => { diff --git a/src/vs/workbench/contrib/void/browser/registerMetrics.ts b/src/vs/workbench/contrib/void/browser/registerMetrics.ts deleted file mode 100644 index 7a6e96ad..00000000 --- a/src/vs/workbench/contrib/void/browser/registerMetrics.ts +++ /dev/null @@ -1,52 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Glass Devtools, Inc. All rights reserved. - * Void Editor additions licensed under the AGPLv3 License. - *--------------------------------------------------------------------------------------------*/ - -import { Disposable } from '../../../../base/common/lifecycle.js'; -import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js'; -import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js'; -import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js'; - -import { posthog } from './react/out/util/posthog.js' - - - -// const buildEnv = 'development'; -// const buildNumber = '1.0.0'; -// const isMac = process.platform === 'darwin'; -// // TODO use commandKey -// const commandKey = isMac ? '⌘' : 'Ctrl'; -// const systemInfo = { -// buildEnv, -// buildNumber, -// isMac, -// } - - - -interface IMetricsService { - readonly _serviceBrand: undefined; -} - -const IMetricsService = createDecorator('metricsService'); -class MetricsService extends Disposable implements IMetricsService { - _serviceBrand: undefined; - - constructor( - @ITelemetryService private readonly _telemetryService: ITelemetryService - ) { - super() - posthog.init('phc_UanIdujHiLp55BkUTjB1AuBXcasVkdqRwgnwRlWESH2', { - api_host: 'https://us.i.posthog.com', - person_profiles: 'identified_only' // we only track events from identified users. We identify them in Sidebar - }) - const deviceId = this._telemetryService.devDeviceId - console.debug('deviceId', deviceId) - posthog.identify(deviceId) - } - - -} - -registerSingleton(IMetricsService, MetricsService, InstantiationType.Eager); diff --git a/src/vs/workbench/contrib/void/browser/void.contribution.ts b/src/vs/workbench/contrib/void/browser/void.contribution.ts index 93466c02..16be4b9c 100644 --- a/src/vs/workbench/contrib/void/browser/void.contribution.ts +++ b/src/vs/workbench/contrib/void/browser/void.contribution.ts @@ -7,14 +7,11 @@ import './registerActions.js' // register Settings -import './registerConfig.js' +import './registerConfig.js' // TODO move this to platform // register inline diffs import './registerInlineDiffs.js' -// register Posthog metrics -import './registerMetrics.js' - // register Sidebar chat import './registerSidebar.js'