From 4559e8f49f6ae9ac05f930b83fc238c558a6f2b5 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Tue, 25 Feb 2025 14:02:48 -0800 Subject: [PATCH 01/13] add gemini directly --- .../positron-assistant/package-lock.json | 155 ++++++++++++------ extensions/positron-assistant/package.json | 3 +- extensions/positron-assistant/src/models.ts | 34 +++- 3 files changed, 139 insertions(+), 53 deletions(-) diff --git a/extensions/positron-assistant/package-lock.json b/extensions/positron-assistant/package-lock.json index 1f1e968d395..fde07dcb07b 100644 --- a/extensions/positron-assistant/package-lock.json +++ b/extensions/positron-assistant/package-lock.json @@ -11,6 +11,7 @@ "@ai-sdk/amazon-bedrock": "^1.1.5", "@ai-sdk/anthropic": "^1.0.5", "@ai-sdk/azure": "^1.1.9", + "@ai-sdk/google": "^1.1.17", "@ai-sdk/google-vertex": "^2.1.8", "@ai-sdk/mistral": "^1.1.6", "@ai-sdk/openai": "^1.0.8", @@ -19,7 +20,7 @@ "@openrouter/ai-sdk-provider": "^0.0.6", "@stylistic/eslint-plugin": "^2.9.0", "@types/node": "^20", - "ai": "^4.1.0", + "ai": "^4.1.46", "eslint": "^9.13.0", "google-auth-library": "^9.15.1", "ollama-ai-provider": "^1.1.0", @@ -122,14 +123,14 @@ } }, "node_modules/@ai-sdk/google": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-1.1.8.tgz", - "integrity": "sha512-8ZOS4p8Qp/7fXWnwNizlFN5aTBu4u3pNlsc7LDFGUtuJXz6j/pAQhqBh3nEaagX3GNuDFT8rxZ1yu82+fYaRpA==", + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-1.1.17.tgz", + "integrity": "sha512-LFdRO+BMUagDplhZExOSr0cfmnoeV1s/gxpIsqt/AWCYnqY/dYGT74nhjbQ+rILeoE8vwnwUu/7OOZexhccm9A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "1.0.7", - "@ai-sdk/provider-utils": "2.1.6" + "@ai-sdk/provider": "1.0.9", + "@ai-sdk/provider-utils": "2.1.10" }, "engines": { "node": ">=18" @@ -158,6 +159,60 @@ "zod": "^3.0.0" } }, + "node_modules/@ai-sdk/google-vertex/node_modules/@ai-sdk/google": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-1.1.8.tgz", + "integrity": "sha512-8ZOS4p8Qp/7fXWnwNizlFN5aTBu4u3pNlsc7LDFGUtuJXz6j/pAQhqBh3nEaagX3GNuDFT8rxZ1yu82+fYaRpA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.0.7", + "@ai-sdk/provider-utils": "2.1.6" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + } + }, + "node_modules/@ai-sdk/google/node_modules/@ai-sdk/provider": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.9.tgz", + "integrity": "sha512-jie6ZJT2ZR0uVOVCDc9R2xCX5I/Dum/wEK28lx21PJx6ZnFAN9EzD2WsPhcDWfCgGx3OAZZ0GyM3CEobXpa9LA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/google/node_modules/@ai-sdk/provider-utils": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.10.tgz", + "integrity": "sha512-4GZ8GHjOFxePFzkl3q42AU0DQOtTQ5w09vmaWUf/pKFXJPizlnzKSUkF0f+VkapIUfDugyMqPMT1ge8XQzVI7Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.0.9", + "eventsource-parser": "^3.0.0", + "nanoid": "^3.3.8", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, "node_modules/@ai-sdk/mistral": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/@ai-sdk/mistral/-/mistral-1.1.6.tgz", @@ -230,14 +285,14 @@ } }, "node_modules/@ai-sdk/react": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.1.6.tgz", - "integrity": "sha512-kP5pimLyNWldw8+0j3ym+AACFEXcQHdELNtk45wDJA3HoH486x/zffdn7yLc3c1DOu5apew+COl8CNL4A+2E4g==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.1.18.tgz", + "integrity": "sha512-2wlWug6NVAc8zh3pgqtvwPkSNTdA6Q4x9CmrNXCeHcXfJkJ+MuHFQz/I7Wb7mLRajf0DAxsFLIhHyBCEuTkDNw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider-utils": "2.1.5", - "@ai-sdk/ui-utils": "1.1.6", + "@ai-sdk/provider-utils": "2.1.10", + "@ai-sdk/ui-utils": "1.1.16", "swr": "^2.2.5", "throttleit": "2.1.0" }, @@ -258,9 +313,9 @@ } }, "node_modules/@ai-sdk/react/node_modules/@ai-sdk/provider": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.6.tgz", - "integrity": "sha512-hwj/gFNxpDgEfTaYzCYoslmw01IY9kWLKl/wf8xuPvHtQIzlfXWmmUwc8PnCwxyt8cKzIuV0dfUghCf68HQ0SA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.9.tgz", + "integrity": "sha512-jie6ZJT2ZR0uVOVCDc9R2xCX5I/Dum/wEK28lx21PJx6ZnFAN9EzD2WsPhcDWfCgGx3OAZZ0GyM3CEobXpa9LA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -271,13 +326,13 @@ } }, "node_modules/@ai-sdk/react/node_modules/@ai-sdk/provider-utils": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.5.tgz", - "integrity": "sha512-PcNR7E4ovZGV/J47gUqaFlvzorgca6uUfN5WzfXJSFWeOeLunN+oxRVwgUOwj0zbmO0yGQTHQD+FHVw8s3Rz8w==", + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.10.tgz", + "integrity": "sha512-4GZ8GHjOFxePFzkl3q42AU0DQOtTQ5w09vmaWUf/pKFXJPizlnzKSUkF0f+VkapIUfDugyMqPMT1ge8XQzVI7Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "1.0.6", + "@ai-sdk/provider": "1.0.9", "eventsource-parser": "^3.0.0", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" @@ -295,14 +350,14 @@ } }, "node_modules/@ai-sdk/ui-utils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.1.6.tgz", - "integrity": "sha512-YAwZhFwpIcvWERIjkET2o2MAwMFfJG18WdtcIjtxxMW7hA0bt5cliOV78DVcwRrxqJ2IKBlxaFmwUjW6M4SdOQ==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.1.16.tgz", + "integrity": "sha512-jfblR2yZVISmNK2zyNzJZFtkgX57WDAUQXcmn3XUBJyo8LFsADu+/vYMn5AOyBi9qJT0RBk11PEtIxIqvByw3Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "1.0.6", - "@ai-sdk/provider-utils": "2.1.5", + "@ai-sdk/provider": "1.0.9", + "@ai-sdk/provider-utils": "2.1.10", "zod-to-json-schema": "^3.24.1" }, "engines": { @@ -318,9 +373,9 @@ } }, "node_modules/@ai-sdk/ui-utils/node_modules/@ai-sdk/provider": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.6.tgz", - "integrity": "sha512-hwj/gFNxpDgEfTaYzCYoslmw01IY9kWLKl/wf8xuPvHtQIzlfXWmmUwc8PnCwxyt8cKzIuV0dfUghCf68HQ0SA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.9.tgz", + "integrity": "sha512-jie6ZJT2ZR0uVOVCDc9R2xCX5I/Dum/wEK28lx21PJx6ZnFAN9EzD2WsPhcDWfCgGx3OAZZ0GyM3CEobXpa9LA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -331,13 +386,13 @@ } }, "node_modules/@ai-sdk/ui-utils/node_modules/@ai-sdk/provider-utils": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.5.tgz", - "integrity": "sha512-PcNR7E4ovZGV/J47gUqaFlvzorgca6uUfN5WzfXJSFWeOeLunN+oxRVwgUOwj0zbmO0yGQTHQD+FHVw8s3Rz8w==", + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.10.tgz", + "integrity": "sha512-4GZ8GHjOFxePFzkl3q42AU0DQOtTQ5w09vmaWUf/pKFXJPizlnzKSUkF0f+VkapIUfDugyMqPMT1ge8XQzVI7Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "1.0.6", + "@ai-sdk/provider": "1.0.9", "eventsource-parser": "^3.0.0", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" @@ -2338,16 +2393,16 @@ } }, "node_modules/ai": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/ai/-/ai-4.1.11.tgz", - "integrity": "sha512-390dahvdwt/kKCq63dyi3M7pq6iWVk9MpfY9C5+RpyDWb50tohUwxntnUvB4Y/cOXGn4Miavdo1g8JbCxsd7wg==", + "version": "4.1.46", + "resolved": "https://registry.npmjs.org/ai/-/ai-4.1.46.tgz", + "integrity": "sha512-VTvAktT69IN1qcNAv7OlcOuR0q4HqUlhkVacrWmMlEoprYykF9EL5RY8IECD5d036Wqg0walwbSKZlA2noHm1A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "1.0.6", - "@ai-sdk/provider-utils": "2.1.5", - "@ai-sdk/react": "1.1.6", - "@ai-sdk/ui-utils": "1.1.6", + "@ai-sdk/provider": "1.0.9", + "@ai-sdk/provider-utils": "2.1.10", + "@ai-sdk/react": "1.1.18", + "@ai-sdk/ui-utils": "1.1.16", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, @@ -2368,9 +2423,9 @@ } }, "node_modules/ai/node_modules/@ai-sdk/provider": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.6.tgz", - "integrity": "sha512-hwj/gFNxpDgEfTaYzCYoslmw01IY9kWLKl/wf8xuPvHtQIzlfXWmmUwc8PnCwxyt8cKzIuV0dfUghCf68HQ0SA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.9.tgz", + "integrity": "sha512-jie6ZJT2ZR0uVOVCDc9R2xCX5I/Dum/wEK28lx21PJx6ZnFAN9EzD2WsPhcDWfCgGx3OAZZ0GyM3CEobXpa9LA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2381,13 +2436,13 @@ } }, "node_modules/ai/node_modules/@ai-sdk/provider-utils": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.5.tgz", - "integrity": "sha512-PcNR7E4ovZGV/J47gUqaFlvzorgca6uUfN5WzfXJSFWeOeLunN+oxRVwgUOwj0zbmO0yGQTHQD+FHVw8s3Rz8w==", + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.10.tgz", + "integrity": "sha512-4GZ8GHjOFxePFzkl3q42AU0DQOtTQ5w09vmaWUf/pKFXJPizlnzKSUkF0f+VkapIUfDugyMqPMT1ge8XQzVI7Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "1.0.6", + "@ai-sdk/provider": "1.0.9", "eventsource-parser": "^3.0.0", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" @@ -3588,9 +3643,9 @@ } }, "node_modules/swr": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.0.tgz", - "integrity": "sha512-NyZ76wA4yElZWBHzSgEJc28a0u6QZvhb6w0azeL2k7+Q1gAzVK+IqQYXhVOC/mzi+HZIozrZvBVeSeOZNR2bqA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.2.tgz", + "integrity": "sha512-RosxFpiabojs75IwQ316DGoDRmOqtiAj0tg8wCcbEu4CiLZBs/a9QNtHV7TUfDXmmlgqij/NqzKq/eLelyv9xA==", "dev": true, "license": "MIT", "dependencies": { @@ -3792,9 +3847,9 @@ } }, "node_modules/zod-to-json-schema": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz", - "integrity": "sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==", + "version": "3.24.3", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.3.tgz", + "integrity": "sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A==", "dev": true, "license": "ISC", "peerDependencies": { diff --git a/extensions/positron-assistant/package.json b/extensions/positron-assistant/package.json index 7668fee9f38..6d327109e57 100644 --- a/extensions/positron-assistant/package.json +++ b/extensions/positron-assistant/package.json @@ -141,6 +141,7 @@ "@ai-sdk/amazon-bedrock": "^1.1.5", "@ai-sdk/anthropic": "^1.0.5", "@ai-sdk/azure": "^1.1.9", + "@ai-sdk/google": "^1.1.17", "@ai-sdk/google-vertex": "^2.1.8", "@ai-sdk/mistral": "^1.1.6", "@ai-sdk/openai": "^1.0.8", @@ -149,7 +150,7 @@ "@openrouter/ai-sdk-provider": "^0.0.6", "@stylistic/eslint-plugin": "^2.9.0", "@types/node": "^20", - "ai": "^4.1.0", + "ai": "^4.1.46", "eslint": "^9.13.0", "google-auth-library": "^9.15.1", "ollama-ai-provider": "^1.1.0", diff --git a/extensions/positron-assistant/src/models.ts b/extensions/positron-assistant/src/models.ts index f86570a1497..a44a023fb47 100644 --- a/extensions/positron-assistant/src/models.ts +++ b/extensions/positron-assistant/src/models.ts @@ -10,6 +10,7 @@ import { ModelConfig } from './config'; import { createAnthropic } from '@ai-sdk/anthropic'; import { createAzure } from '@ai-sdk/azure'; import { createVertex } from '@ai-sdk/google-vertex'; +import { createGoogleGenerativeAI } from '@ai-sdk/google'; import { createOpenAI } from '@ai-sdk/openai'; import { createMistral } from '@ai-sdk/mistral'; import { createOllama } from 'ollama-ai-provider'; @@ -202,7 +203,7 @@ abstract class AILanguageModel implements positron.ai.LanguageModelChatProvider } class AnthropicLanguageModel extends AILanguageModel implements positron.ai.LanguageModelChatProvider { - protected model; + protected model: ai.LanguageModelV1; static source: positron.ai.LanguageModelSource = { type: positron.PositronLanguageModelType.Chat, @@ -439,6 +440,34 @@ export function newLanguageModel(config: ModelConfig): positron.ai.LanguageModel return new providerClasses[config.provider as keyof typeof providerClasses](config); } +class GoogleLanguageModel extends AILanguageModel implements positron.ai.LanguageModelChatProvider { + protected model: ai.LanguageModelV1; + + static source: positron.ai.LanguageModelSource = { + type: positron.PositronLanguageModelType.Chat, + provider: { + id: 'google', + displayName: 'Google Generative AI' + }, + supportedOptions: ['toolCalls', 'project', 'location'], + defaults: { + name: 'Gemini 2.0 Flash', + model: 'gemini-2.0-flash-exp', + project: undefined, + location: undefined, + toolCalls: true, + }, + }; + + constructor(_config: ModelConfig) { + super(_config); + this.model = createGoogleGenerativeAI({ + apiKey: this._config.apiKey, + })(this._config.model); + } +} + + export const languageModels = [ AnthropicLanguageModel, AzureLanguageModel, @@ -447,5 +476,6 @@ export const languageModels = [ OpenAILanguageModel, OpenRouterLanguageModel, OllamaLanguageModel, - VertexLanguageModel + VertexLanguageModel, + GoogleLanguageModel ]; From 394561300fcf7080ba3a723c18988c075262eef9 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Tue, 25 Feb 2025 14:21:29 -0800 Subject: [PATCH 02/13] add gemini model from API key --- extensions/positron-assistant/src/models.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/extensions/positron-assistant/src/models.ts b/extensions/positron-assistant/src/models.ts index a44a023fb47..8abb6be63be 100644 --- a/extensions/positron-assistant/src/models.ts +++ b/extensions/positron-assistant/src/models.ts @@ -426,6 +426,7 @@ export function newLanguageModel(config: ModelConfig): positron.ai.LanguageModel 'anthropic': AnthropicLanguageModel, 'azure': AzureLanguageModel, 'bedrock': AWSLanguageModel, + 'google': GoogleLanguageModel, 'mistral': MistralLanguageModel, 'ollama': OllamaLanguageModel, 'openai': OpenAILanguageModel, @@ -449,13 +450,12 @@ class GoogleLanguageModel extends AILanguageModel implements positron.ai.Languag id: 'google', displayName: 'Google Generative AI' }, - supportedOptions: ['toolCalls', 'project', 'location'], + supportedOptions: ['baseUrl', 'apiKey'], defaults: { name: 'Gemini 2.0 Flash', model: 'gemini-2.0-flash-exp', - project: undefined, - location: undefined, - toolCalls: true, + baseUrl: 'https://generativelanguage.googleapis.com/v1beta', + apiKey: undefined, }, }; @@ -463,19 +463,20 @@ class GoogleLanguageModel extends AILanguageModel implements positron.ai.Languag super(_config); this.model = createGoogleGenerativeAI({ apiKey: this._config.apiKey, + baseURL: this._config.baseUrl, })(this._config.model); } } export const languageModels = [ + AWSLanguageModel, AnthropicLanguageModel, AzureLanguageModel, - AWSLanguageModel, + GoogleLanguageModel, MistralLanguageModel, + OllamaLanguageModel, OpenAILanguageModel, OpenRouterLanguageModel, - OllamaLanguageModel, VertexLanguageModel, - GoogleLanguageModel ]; From 70f905614b797c9c1a5f0e252213fb8818402db4 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Tue, 25 Feb 2025 14:32:28 -0800 Subject: [PATCH 03/13] add gemini as a FIM option --- .../positron-assistant/src/completion.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/extensions/positron-assistant/src/completion.ts b/extensions/positron-assistant/src/completion.ts index 53c9454d27d..5e8fe793283 100644 --- a/extensions/positron-assistant/src/completion.ts +++ b/extensions/positron-assistant/src/completion.ts @@ -20,6 +20,7 @@ import { createAzure } from '@ai-sdk/azure'; import { loadSetting } from '@ai-sdk/provider-utils'; import { GoogleAuth } from 'google-auth-library'; +import { createGoogleGenerativeAI } from '@ai-sdk/google'; const mdDir = `${EXTENSION_ROOT_DIR}/src/md/`; @@ -548,6 +549,33 @@ class VertexCompletion extends FimPromptCompletion { } } +class GoogleCompletion extends FimPromptCompletion { + protected model: ai.LanguageModelV1; + + static source: positron.ai.LanguageModelSource = { + type: positron.PositronLanguageModelType.Completion, + provider: { + id: 'google', + displayName: 'Google Generative AI' + }, + supportedOptions: ['baseUrl', 'apiKey'], + defaults: { + name: 'Gemini 2.0 Flash-Lite', + model: 'gemini-2.0-flash-lite', + baseUrl: 'https://generativelanguage.googleapis.com/v1beta', + apiKey: undefined, + }, + }; + + constructor(_config: ModelConfig) { + super(_config); + this.model = createGoogleGenerativeAI({ + apiKey: this._config.apiKey, + baseURL: this._config.baseUrl, + })(this._config.model); + } +} + class AzureCompletion extends FimPromptCompletion { protected model: ai.LanguageModelV1; @@ -583,6 +611,7 @@ export function newCompletionProvider(config: ModelConfig): vscode.InlineComplet 'azure': AzureCompletion, 'bedrock': AWSCompletion, 'deepseek': DeepSeekCompletion, + 'google': GoogleCompletion, 'mistral': MistralCompletion, 'ollama': OllamaCompletion, 'openai': OpenAICompletion, @@ -605,6 +634,7 @@ export const completionModels = [ AzureCompletion, DeepSeekCompletion, MistralCompletion, + GoogleCompletion, OllamaCompletion, OpenAICompletion, OpenAILegacyCompletion, From 31236da0cdb7a4814dd8441e5f21a1c75b442f15 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Tue, 25 Feb 2025 14:32:49 -0800 Subject: [PATCH 04/13] I guess this makes me a prompt engineer?!?! --- .../positron-assistant/src/md/prompts/completion/fim.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extensions/positron-assistant/src/md/prompts/completion/fim.md b/extensions/positron-assistant/src/md/prompts/completion/fim.md index 6756256e4eb..02434885f48 100644 --- a/extensions/positron-assistant/src/md/prompts/completion/fim.md +++ b/extensions/positron-assistant/src/md/prompts/completion/fim.md @@ -2,5 +2,8 @@ The user will provide code before and after their current cursor position in the Code before the cursor will be given in tags. Code after the cursor will be given in tags, which might be empty. The user might provide additional code in tags. -You should respond ONLY with valid code to be inserted at the cursor. +You should respond ONLY with valid code to be inserted at the cursor. Do not +include formatting symbols or Markdown code blocks. Do not include any +additional text in your response. + To start on a new line, begin your response with a newline. From a980f077360a86dbb82bc2fb01bbdb599851f883 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Tue, 25 Feb 2025 15:57:38 -0800 Subject: [PATCH 05/13] add google for validation; bump bedrock version for ai-sdk compat --- .../positron-assistant/package-lock.json | 492 ++++++++++++++---- extensions/positron-assistant/package.json | 3 +- 2 files changed, 402 insertions(+), 93 deletions(-) diff --git a/extensions/positron-assistant/package-lock.json b/extensions/positron-assistant/package-lock.json index fde07dcb07b..d8fc877dc09 100644 --- a/extensions/positron-assistant/package-lock.json +++ b/extensions/positron-assistant/package-lock.json @@ -8,7 +8,7 @@ "name": "positron-assistant", "version": "0.0.1", "devDependencies": { - "@ai-sdk/amazon-bedrock": "^1.1.5", + "@ai-sdk/amazon-bedrock": "^1.1.6", "@ai-sdk/anthropic": "^1.0.5", "@ai-sdk/azure": "^1.1.9", "@ai-sdk/google": "^1.1.17", @@ -33,14 +33,14 @@ } }, "node_modules/@ai-sdk/amazon-bedrock": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-1.1.5.tgz", - "integrity": "sha512-CEHk/EzpfTaVPZtGD5baDescDXNHS9n2XOjkCO3g6MDiPiNDW0Xn4+kko21E6QsdjYQ+bmLVWiWj7ikzc3OD5A==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-1.1.6.tgz", + "integrity": "sha512-h6SJWpku+i8OsSz0A4RT2g2uD+3E0SUgWHsWRIpxmPNgM1DnH6lgSby5sxqAZDY5xJyJtRFW5vB9G3GEBjHy/g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "1.0.6", - "@ai-sdk/provider-utils": "2.1.5", + "@ai-sdk/provider": "1.0.7", + "@ai-sdk/provider-utils": "2.1.6", "@aws-sdk/client-bedrock-runtime": "^3.663.0" }, "engines": { @@ -50,43 +50,6 @@ "zod": "^3.0.0" } }, - "node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/provider": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.6.tgz", - "integrity": "sha512-hwj/gFNxpDgEfTaYzCYoslmw01IY9kWLKl/wf8xuPvHtQIzlfXWmmUwc8PnCwxyt8cKzIuV0dfUghCf68HQ0SA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/provider-utils": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.5.tgz", - "integrity": "sha512-PcNR7E4ovZGV/J47gUqaFlvzorgca6uUfN5WzfXJSFWeOeLunN+oxRVwgUOwj0zbmO0yGQTHQD+FHVw8s3Rz8w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "1.0.6", - "eventsource-parser": "^3.0.0", - "nanoid": "^3.3.8", - "secure-json-parse": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.0.0" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } - } - }, "node_modules/@ai-sdk/anthropic": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-1.1.6.tgz", @@ -560,27 +523,27 @@ } }, "node_modules/@aws-sdk/client-bedrock-runtime": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.734.0.tgz", - "integrity": "sha512-e4E7UkJE2CXht5gBJ8KuDnxlQgx35wW2gUeUvXJZ3fpgIrtdgd9bQmPGZ61OSQ+1K4oCJJ6TLekru1lsPpDm0w==", + "version": "3.755.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.755.0.tgz", + "integrity": "sha512-g5Adp2haJn3d1M7he4KSBUO/QAJuDNhnCNSZ4Ud30F0WvX07C7nZUDzKOi8cYa8xeXK6gpSlk6DdgcJflXdfXA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.734.0", - "@aws-sdk/credential-provider-node": "3.734.0", + "@aws-sdk/core": "3.750.0", + "@aws-sdk/credential-provider-node": "3.750.0", "@aws-sdk/middleware-host-header": "3.734.0", "@aws-sdk/middleware-logger": "3.734.0", "@aws-sdk/middleware-recursion-detection": "3.734.0", - "@aws-sdk/middleware-user-agent": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.750.0", "@aws-sdk/region-config-resolver": "3.734.0", "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.750.0", "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.1", + "@smithy/core": "^3.1.4", "@smithy/eventstream-serde-browser": "^4.0.1", "@smithy/eventstream-serde-config-resolver": "^4.0.1", "@smithy/eventstream-serde-node": "^4.0.1", @@ -588,25 +551,25 @@ "@smithy/hash-node": "^4.0.1", "@smithy/invalid-dependency": "^4.0.1", "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.2", - "@smithy/middleware-retry": "^4.0.3", - "@smithy/middleware-serde": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.5", + "@smithy/middleware-retry": "^4.0.6", + "@smithy/middleware-serde": "^4.0.2", "@smithy/middleware-stack": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/node-http-handler": "^4.0.2", "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.2", + "@smithy/smithy-client": "^4.1.5", "@smithy/types": "^4.1.0", "@smithy/url-parser": "^4.0.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.3", - "@smithy/util-defaults-mode-node": "^4.0.3", + "@smithy/util-defaults-mode-browser": "^4.0.6", + "@smithy/util-defaults-mode-node": "^4.0.6", "@smithy/util-endpoints": "^3.0.1", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", - "@smithy/util-stream": "^4.0.2", + "@smithy/util-stream": "^4.1.1", "@smithy/util-utf8": "^4.0.0", "@types/uuid": "^9.0.1", "tslib": "^2.6.2", @@ -616,6 +579,351 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/client-sso": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.750.0.tgz", + "integrity": "sha512-y0Rx6pTQXw0E61CaptpZF65qNggjqOgymq/RYZU5vWba5DGQ+iqGt8Yq8s+jfBoBBNXshxq8l8Dl5Uq/JTY1wg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.750.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.750.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.750.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.4", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.5", + "@smithy/middleware-retry": "^4.0.6", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.2", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.5", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.6", + "@smithy/util-defaults-mode-node": "^4.0.6", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/core": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.750.0.tgz", + "integrity": "sha512-bZ5K7N5L4+Pa2epbVpUQqd1XLG2uU8BGs/Sd+2nbgTf+lNQJyIxAg/Qsrjz9MzmY8zzQIeRQEkNmR6yVAfCmmQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.734.0", + "@smithy/core": "^3.1.4", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/signature-v4": "^5.0.1", + "@smithy/smithy-client": "^4.1.5", + "@smithy/types": "^4.1.0", + "@smithy/util-middleware": "^4.0.1", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.750.0.tgz", + "integrity": "sha512-In6bsG0p/P31HcH4DBRKBbcDS/3SHvEPjfXV8ODPWZO/l3/p7IRoYBdQ07C9R+VMZU2D0+/Sc/DWK/TUNDk1+Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.750.0.tgz", + "integrity": "sha512-wFB9qqfa20AB0dElsQz5ZlZT5o+a+XzpEpmg0erylmGYqEOvh8NQWfDUVpRmQuGq9VbvW/8cIbxPoNqEbPtuWQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/node-http-handler": "^4.0.2", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.5", + "@smithy/types": "^4.1.0", + "@smithy/util-stream": "^4.1.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.750.0.tgz", + "integrity": "sha512-2YIZmyEr5RUd3uxXpxOLD9G67Bibm4I/65M6vKFP17jVMUT+R1nL7mKqmhEVO2p+BoeV+bwMyJ/jpTYG368PCg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.750.0", + "@aws-sdk/credential-provider-env": "3.750.0", + "@aws-sdk/credential-provider-http": "3.750.0", + "@aws-sdk/credential-provider-process": "3.750.0", + "@aws-sdk/credential-provider-sso": "3.750.0", + "@aws-sdk/credential-provider-web-identity": "3.750.0", + "@aws-sdk/nested-clients": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.750.0.tgz", + "integrity": "sha512-THWHHAceLwsOiowPEmKyhWVDlEUxH07GHSw5AQFDvNQtGKOQl0HSIFO1mKObT2Q2Vqzji9Bq8H58SO5BFtNPRw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.750.0", + "@aws-sdk/credential-provider-http": "3.750.0", + "@aws-sdk/credential-provider-ini": "3.750.0", + "@aws-sdk/credential-provider-process": "3.750.0", + "@aws-sdk/credential-provider-sso": "3.750.0", + "@aws-sdk/credential-provider-web-identity": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.750.0.tgz", + "integrity": "sha512-Q78SCH1n0m7tpu36sJwfrUSxI8l611OyysjQeMiIOliVfZICEoHcLHLcLkiR+tnIpZ3rk7d2EQ6R1jwlXnalMQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.750.0.tgz", + "integrity": "sha512-FGYrDjXN/FOQVi/t8fHSv8zCk+NEvtFnuc4cZUj5OIbM4vrfFc5VaPyn41Uza3iv6Qq9rZg0QOwWnqK8lNrqUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.750.0", + "@aws-sdk/core": "3.750.0", + "@aws-sdk/token-providers": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.750.0.tgz", + "integrity": "sha512-Nz8zs3YJ+GOTSrq+LyzbbC1Ffpt7pK38gcOyNZv76pP5MswKTUKNYBJehqwa+i7FcFQHsCk3TdhR8MT1ZR23uA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.750.0", + "@aws-sdk/nested-clients": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.750.0.tgz", + "integrity": "sha512-YYcslDsP5+2NZoN3UwuhZGkhAHPSli7HlJHBafBrvjGV/I9f8FuOO1d1ebxGdEP4HyRXUGyh+7Ur4q+Psk0ryw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@smithy/core": "^3.1.4", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/nested-clients": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.750.0.tgz", + "integrity": "sha512-OH68BRF0rt9nDloq4zsfeHI0G21lj11a66qosaljtEP66PWm7tQ06feKbFkXHT5E1K3QhJW3nVyK8v2fEBY5fg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.750.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.750.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.750.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.4", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.5", + "@smithy/middleware-retry": "^4.0.6", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.2", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.5", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.6", + "@smithy/util-defaults-mode-node": "^4.0.6", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/token-providers": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.750.0.tgz", + "integrity": "sha512-X/KzqZw41iWolwNdc8e3RMcNSMR364viHv78u6AefXOO5eRM40c4/LuST1jDzq35/LpnqRhL7/MuixOetw+sFw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/nested-clients": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-endpoints": { + "version": "3.743.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.743.0.tgz", + "integrity": "sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.734.0", + "@smithy/types": "^4.1.0", + "@smithy/util-endpoints": "^3.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.750.0.tgz", + "integrity": "sha512-84HJj9G9zbrHX2opLk9eHfDceB+UIHVrmflMzWHpsmo9fDuro/flIBqaVDlE021Osj6qIM0SJJcnL6s23j7JEw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.750.0", + "@aws-sdk/types": "3.734.0", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, "node_modules/@aws-sdk/client-cognito-identity": { "version": "3.734.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.734.0.tgz", @@ -1461,9 +1769,9 @@ } }, "node_modules/@smithy/core": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.2.tgz", - "integrity": "sha512-htwQXkbdF13uwwDevz9BEzL5ABK+1sJpVQXywwGSH973AVOvisHNfpcB8A8761G6XgHoS2kHPqc9DqHJ2gp+/Q==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.5.tgz", + "integrity": "sha512-HLclGWPkCsekQgsyzxLhCQLa8THWXtB5PxyYN+2O6nkyLt550KQKTlbV2D1/j5dNIQapAZM1+qFnpBFxZQkgCA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1472,7 +1780,7 @@ "@smithy/types": "^4.1.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.1", - "@smithy/util-stream": "^4.0.2", + "@smithy/util-stream": "^4.1.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -1648,13 +1956,13 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.3.tgz", - "integrity": "sha512-YdbmWhQF5kIxZjWqPIgboVfi8i5XgiYMM7GGKFMTvBei4XjNQfNv8sukT50ITvgnWKKKpOtp0C0h7qixLgb77Q==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.6.tgz", + "integrity": "sha512-ftpmkTHIFqgaFugcjzLZv3kzPEFsBFSnq1JsIkr2mwFzCraZVhQk2gqN51OOeRxqhbPTkRFj39Qd2V91E/mQxg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.1.2", + "@smithy/core": "^3.1.5", "@smithy/middleware-serde": "^4.0.2", "@smithy/node-config-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", @@ -1668,16 +1976,16 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.4.tgz", - "integrity": "sha512-wmxyUBGHaYUqul0wZiset4M39SMtDBOtUr2KpDuftKNN74Do9Y36Go6Eqzj9tL0mIPpr31ulB5UUtxcsCeGXsQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.7.tgz", + "integrity": "sha512-58j9XbUPLkqAcV1kHzVX/kAR16GT+j7DUZJqwzsxh1jtz7G82caZiGyyFgUvogVfNTg3TeAOIJepGc8TXF4AVQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/service-error-classification": "^4.0.1", - "@smithy/smithy-client": "^4.1.3", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", @@ -1733,9 +2041,9 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", - "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz", + "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1854,18 +2162,18 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.3.tgz", - "integrity": "sha512-A2Hz85pu8BJJaYFdX8yb1yocqigyqBzn+OVaVgm+Kwi/DkN8vhN2kbDVEfADo6jXf5hPKquMLGA3UINA64UZ7A==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.6.tgz", + "integrity": "sha512-UYDolNg6h2O0L+cJjtgSyKKvEKCOa/8FHYJnBobyeoeWDmNpXjwOAtw16ezyeu1ETuuLEOZbrynK0ZY1Lx9Jbw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.1.2", - "@smithy/middleware-endpoint": "^4.0.3", + "@smithy/core": "^3.1.5", + "@smithy/middleware-endpoint": "^4.0.6", "@smithy/middleware-stack": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", - "@smithy/util-stream": "^4.0.2", + "@smithy/util-stream": "^4.1.2", "tslib": "^2.6.2" }, "engines": { @@ -1969,14 +2277,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.4.tgz", - "integrity": "sha512-Ej1bV5sbrIfH++KnWxjjzFNq9nyP3RIUq2c9Iqq7SmMO/idUR24sqvKH2LUQFTSPy/K7G4sB2m8n7YYlEAfZaw==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.7.tgz", + "integrity": "sha512-CZgDDrYHLv0RUElOsmZtAnp1pIjwDVCSuZWOPhIOBvG36RDfX1Q9+6lS61xBf+qqvHoqRjHxgINeQz47cYFC2Q==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.3", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -1986,9 +2294,9 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.4.tgz", - "integrity": "sha512-HE1I7gxa6yP7ZgXPCFfZSDmVmMtY7SHqzFF55gM/GPegzZKaQWZZ+nYn9C2Cc3JltCMyWe63VPR3tSFDEvuGjw==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.7.tgz", + "integrity": "sha512-79fQW3hnfCdrfIi1soPbK3zmooRFnLpSx3Vxi6nUlqaaQeC5dm8plt4OTNDNqEEEDkvKghZSaoti684dQFVrGQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1996,7 +2304,7 @@ "@smithy/credential-provider-imds": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.3", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, @@ -2062,14 +2370,14 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.0.2.tgz", - "integrity": "sha512-0eZ4G5fRzIoewtHtwaYyl8g2C+osYOT4KClXgfdNEDAgkbe2TYPqcnw4GAWabqkZCax2ihRGPe9LZnsPdIUIHA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz", + "integrity": "sha512-44PKEqQ303d3rlQuiDpcCcu//hV8sn+u2JBo84dWCE0rvgeiVl0IlLMagbU++o0jCWhYCsHaAt9wZuZqNe05Hw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/node-http-handler": "^4.0.2", + "@smithy/node-http-handler": "^4.0.3", "@smithy/types": "^4.1.0", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", diff --git a/extensions/positron-assistant/package.json b/extensions/positron-assistant/package.json index 6d327109e57..b2a234439ac 100644 --- a/extensions/positron-assistant/package.json +++ b/extensions/positron-assistant/package.json @@ -102,6 +102,7 @@ "azure", "echo", "error", + "google", "mistral", "ollama", "openai", @@ -138,7 +139,7 @@ "lint": "eslint src --ext ts" }, "devDependencies": { - "@ai-sdk/amazon-bedrock": "^1.1.5", + "@ai-sdk/amazon-bedrock": "^1.1.6", "@ai-sdk/anthropic": "^1.0.5", "@ai-sdk/azure": "^1.1.9", "@ai-sdk/google": "^1.1.17", From 4d98f852af8e9568993ab85fe306b4f4b268aeff Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Wed, 26 Feb 2025 10:19:25 -0800 Subject: [PATCH 06/13] provide an alternate way to store api keys in web mode --- extensions/positron-assistant/src/config.ts | 44 ++++++++++++++++--- .../positron-assistant/src/extension.ts | 20 +++++---- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/extensions/positron-assistant/src/config.ts b/extensions/positron-assistant/src/config.ts index 506d8910d18..4c1f6192806 100644 --- a/extensions/positron-assistant/src/config.ts +++ b/extensions/positron-assistant/src/config.ts @@ -12,6 +12,38 @@ interface StoredModelConfig extends Omit; + get(key: string): Thenable; + delete(key: string): Thenable; +} + +export class EncryptedSecretStorage implements SecretStorage { + constructor(private context: vscode.ExtensionContext) { } + store(key: string, value: string): Thenable { + return this.context.secrets.store(key, value); + } + get(key: string): Thenable { + return this.context.secrets.get(key); + } + delete(key: string): Thenable { + return this.context.secrets.delete(key); + } +} + +export class GlobalSecretStorage implements SecretStorage { + constructor(private context: vscode.ExtensionContext) { } + store(key: string, value: string): Thenable { + return this.context.globalState.update(key, value); + } + get(key: string): Thenable { + return Promise.resolve(this.context.globalState.get(key)); + } + delete(key: string): Thenable { + return this.context.globalState.update(key, undefined); + } +} + export interface ModelConfig extends StoredModelConfig { apiKey: string; } @@ -22,12 +54,12 @@ export function getStoredModels(): StoredModelConfig[] { return storedConfigs; } -export async function getModelConfigurations(context: vscode.ExtensionContext): Promise { +export async function getModelConfigurations(storage: SecretStorage): Promise { const storedConfigs = getStoredModels(); const fullConfigs: ModelConfig[] = await Promise.all( storedConfigs.map(async (config) => { - const apiKey = await context.secrets.get(`apiKey-${config.id}`); + const apiKey = await storage.get(`apiKey-${config.id}`); return { ...config, apiKey: apiKey || '' @@ -38,7 +70,7 @@ export async function getModelConfigurations(context: vscode.ExtensionContext): return fullConfigs; } -export async function showConfigurationDialog(context: vscode.ExtensionContext) { +export async function showConfigurationDialog(storage: SecretStorage) { // Gather model sources const sources = [...languageModels, ...completionModels].map((provider) => provider.source); @@ -67,7 +99,7 @@ export async function showConfigurationDialog(context: vscode.ExtensionContext) // Store API key in secret storage if (apiKey) { - await context.secrets.store(`apiKey-${id}`, apiKey); + await storage.store(`apiKey-${id}`, apiKey); } // Get existing configurations @@ -97,7 +129,7 @@ export async function showConfigurationDialog(context: vscode.ExtensionContext) } -export async function deleteConfiguration(context: vscode.ExtensionContext, id: string) { +export async function deleteConfiguration(storage: SecretStorage, id: string) { const config = vscode.workspace.getConfiguration('positron.assistant'); const existingConfigs = config.get('models') || []; const updatedConfigs = existingConfigs.filter(config => config.id !== id); @@ -108,5 +140,5 @@ export async function deleteConfiguration(context: vscode.ExtensionContext, id: vscode.ConfigurationTarget.Global ); - await context.secrets.delete(`apiKey-${id}`); + await storage.delete(`apiKey-${id}`); } diff --git a/extensions/positron-assistant/src/extension.ts b/extensions/positron-assistant/src/extension.ts index fcb0c8b19ef..4fb9b38cb8f 100644 --- a/extensions/positron-assistant/src/extension.ts +++ b/extensions/positron-assistant/src/extension.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import * as positron from 'positron'; -import { getModelConfigurations, showConfigurationDialog } from './config'; +import { EncryptedSecretStorage, getModelConfigurations, GlobalSecretStorage, SecretStorage, showConfigurationDialog } from './config'; import { newLanguageModel } from './models'; import participants from './participants'; import { newCompletionProvider, registerHistoryTracking } from './completion'; @@ -27,12 +27,12 @@ function disposeParticipants() { participantDisposables = []; } -async function registerModels(context: vscode.ExtensionContext) { +async function registerModels(context: vscode.ExtensionContext, storage: SecretStorage) { // Dispose of existing models disposeModels(); try { - const modelConfigs = await getModelConfigurations(context); + const modelConfigs = await getModelConfigurations(storage); // Register with Language Model API modelConfigs.filter(config => config.type === 'chat').forEach((config, idx) => { // We need at least one default and one non-default model for the dropdown to appear. @@ -86,10 +86,10 @@ function registerParticipants(context: vscode.ExtensionContext) { }); } -function registerAddModelConfigurationCommand(context: vscode.ExtensionContext) { +function registerAddModelConfigurationCommand(context: vscode.ExtensionContext, storage: SecretStorage) { context.subscriptions.push( vscode.commands.registerCommand('positron-assistant.addModelConfiguration', () => { - showConfigurationDialog(context); + showConfigurationDialog(storage); }) ); } @@ -101,17 +101,21 @@ function registerMappedEditsProvider(context: vscode.ExtensionContext) { } function registerAssistant(context: vscode.ExtensionContext) { + + // Initialize secret storage. In web mode, use global storage; otherwise, use encrypted storage. + const storage = vscode.env.uiKind === vscode.UIKind.Web ? new GlobalSecretStorage(context) : new EncryptedSecretStorage(context); + // Register chat participants registerParticipants(context); // Register configured language models - registerModels(context); + registerModels(context, storage); // Track opened files for completion context registerHistoryTracking(context); // Configuration modal command - registerAddModelConfigurationCommand(context); + registerAddModelConfigurationCommand(context, storage); // Register mapped edits provider registerMappedEditsProvider(context); @@ -120,7 +124,7 @@ function registerAssistant(context: vscode.ExtensionContext) { context.subscriptions.push( vscode.workspace.onDidChangeConfiguration(e => { if (e.affectsConfiguration('positron.assistant.models')) { - registerModels(context); + registerModels(context, storage); } }) ); From f253c3f4a38f790a95e85fdc4b1e3373e4cc8175 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Wed, 26 Feb 2025 10:26:12 -0800 Subject: [PATCH 07/13] new codicon --- .../positron-assistant/src/participants.ts | 2 +- .../browser/ui/codicons/codicon/codicon.ttf | Bin 102164 -> 102568 bytes src/vs/base/common/codiconsLibrary.ts | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/positron-assistant/src/participants.ts b/extensions/positron-assistant/src/participants.ts index d232ebef922..71030bfcffd 100644 --- a/extensions/positron-assistant/src/participants.ts +++ b/extensions/positron-assistant/src/participants.ts @@ -17,7 +17,7 @@ const mdDir = `${EXTENSION_ROOT_DIR}/src/md/`; class PositronAssistantParticipant implements positron.ai.ChatParticipant { readonly id = 'positron.positron-assistant'; - readonly iconPath = new vscode.ThemeIcon('positron-posit-logo'); + readonly iconPath = new vscode.ThemeIcon('positron-assistant'); readonly agentData: positron.ai.ChatAgentData = { id: this.id, name: 'positron-assistant', diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf index 6fea3baed01b568a03307f9aa690c5321f73b85b..ce87bb672a8592ff2cca933e8840efee82a6b66d 100644 GIT binary patch delta 5105 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 V_hy!r<(HLbmXsfz>BZsT{{qxVaRC4T delta 4758 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 Date: Wed, 26 Feb 2025 11:00:25 -0800 Subject: [PATCH 08/13] use assistant logo for chat panel --- extensions/positron-assistant/src/participants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/positron-assistant/src/participants.ts b/extensions/positron-assistant/src/participants.ts index 71030bfcffd..10cc1f402d0 100644 --- a/extensions/positron-assistant/src/participants.ts +++ b/extensions/positron-assistant/src/participants.ts @@ -88,7 +88,7 @@ class PositronAssistantParticipant implements positron.ai.ChatParticipant { message.isTrusted = true; return { - icon: new vscode.ThemeIcon('positron-posit-logo'), + icon: new vscode.ThemeIcon('positron-assistant'), title: 'Positron Assistant', message, }; From d3aa3a69ff1c37b784f4b0376c5285d633328b36 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Wed, 26 Feb 2025 11:00:43 -0800 Subject: [PATCH 09/13] don't register API test as default participant --- extensions/vscode-api-tests/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 5f7681bf9d6..0aee032070b 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -74,7 +74,6 @@ "id": "api-test.participant", "name": "participant", "description": "test", - "isDefault": true, "commands": [ { "name": "hello", From 1fb11a63be7fe9cbc2479be529d1537983e7bb47 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Wed, 26 Feb 2025 16:24:05 -0800 Subject: [PATCH 10/13] store config in global state --- extensions/positron-assistant/package.json | 76 ------------------- .../positron-assistant/package.nls.json | 14 +--- extensions/positron-assistant/src/config.ts | 36 ++++----- .../positron-assistant/src/extension.ts | 7 +- .../positron-assistant/src/participants.ts | 18 +++-- 5 files changed, 32 insertions(+), 119 deletions(-) diff --git a/extensions/positron-assistant/package.json b/extensions/positron-assistant/package.json index b2a234439ac..01a1e1cac9f 100644 --- a/extensions/positron-assistant/package.json +++ b/extensions/positron-assistant/package.json @@ -53,82 +53,6 @@ "type": "boolean", "default": false, "description": "%configuration.enable.description%" - }, - "positron.assistant.models": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "%configuration.models.id.description%" - }, - "name": { - "type": "string", - "description": "%configuration.models.name.description%" - }, - "model": { - "type": "string", - "description": "%configuration.models.model.description%" - }, - "baseUrl": { - "type": "string", - "description": "%configuration.models.baseUrl.description%" - }, - "numCtx": { - "type": "number", - "description": "%configuration.models.numCtx.description%" - }, - "toolCalls": { - "type": "boolean", - "description": "%configuration.models.toolCalls.description%" - }, - "project": { - "type": "string", - "description": "%configuration.models.project.description%" - }, - "location": { - "type": "string", - "description": "%configuration.models.location.description%" - }, - "resourceName": { - "type": "string", - "description": "%configuration.models.resourceName.description%" - }, - "provider": { - "type": "string", - "enum": [ - "anthropic", - "azure", - "echo", - "error", - "google", - "mistral", - "ollama", - "openai", - "openai-legacy", - "openrouter", - "bedrock", - "vertex", - "vertex-legacy" - ], - "description": "%configuration.models.provider.description%" - }, - "type": { - "enum": [ - "chat", - "completion" - ], - "description": "%configuration.models.type.description%" - } - }, - "required": [ - "name", - "provider" - ], - "additionalProperties": false - }, - "description": "%configuration.models.description%" } } } diff --git a/extensions/positron-assistant/package.nls.json b/extensions/positron-assistant/package.nls.json index f71300fa48d..99588e5a7b4 100644 --- a/extensions/positron-assistant/package.nls.json +++ b/extensions/positron-assistant/package.nls.json @@ -3,17 +3,5 @@ "description": "Provides default assistant and language models for Positron.", "commands.addModelConfiguration.title": "Add Language Model", "commands.addModelConfiguration.category": "Positron Assistant", - "configuration.enable.description": "Enable Positron Assistant (experimental)", - "configuration.models.description": "Array of language model configurations.", - "configuration.models.id.description": "Identifier for the model provider, used for API key storage.", - "configuration.models.name.description": "Display name for the model.", - "configuration.models.model.description": "The specific model to use.", - "configuration.models.baseUrl.description": "URL prefix for API calls.", - "configuration.models.numCtx.description": "Context window size.", - "configuration.models.toolCalls.description": "Should the LLM make tool calls?", - "configuration.models.project.description": "Google Cloud Project ID.", - "configuration.models.location.description": "Google Cloud Location.", - "configuration.models.resourceName.description": "Azure resource name.", - "configuration.models.provider.description": "The language model provider.", - "configuration.models.type.description": "Type of model; chat participant or code completion." + "configuration.enable.description": "Enable Positron Assistant (experimental)" } diff --git a/extensions/positron-assistant/src/config.ts b/extensions/positron-assistant/src/config.ts index 4c1f6192806..463d84908eb 100644 --- a/extensions/positron-assistant/src/config.ts +++ b/extensions/positron-assistant/src/config.ts @@ -48,14 +48,12 @@ export interface ModelConfig extends StoredModelConfig { apiKey: string; } -export function getStoredModels(): StoredModelConfig[] { - const config = vscode.workspace.getConfiguration('positron.assistant'); - const storedConfigs = config.get('models') || []; - return storedConfigs; +export function getStoredModels(context: vscode.ExtensionContext): StoredModelConfig[] { + return context.globalState.get('positron.assistant.models') || []; } -export async function getModelConfigurations(storage: SecretStorage): Promise { - const storedConfigs = getStoredModels(); +export async function getModelConfigurations(context: vscode.ExtensionContext, storage: SecretStorage): Promise { + const storedConfigs = getStoredModels(context); const fullConfigs: ModelConfig[] = await Promise.all( storedConfigs.map(async (config) => { @@ -70,7 +68,7 @@ export async function getModelConfigurations(storage: SecretStorage): Promise provider.source); @@ -103,8 +101,7 @@ export async function showConfigurationDialog(storage: SecretStorage) { } // Get existing configurations - const config = vscode.workspace.getConfiguration('positron.assistant'); - const existingConfigs = config.get('models') || []; + const existingConfigs: Array = context.globalState.get('positron.assistant.models') || []; // Add new configuration const newConfig: StoredModelConfig = { @@ -115,11 +112,10 @@ export async function showConfigurationDialog(storage: SecretStorage) { ...otherConfig, }; - // Update settings.json - await config.update( - 'models', - [...existingConfigs, newConfig], - vscode.ConfigurationTarget.Global + // Update global state + await context.globalState.update( + 'positron.assistant.models', + [...existingConfigs, newConfig] ); vscode.window.showInformationMessage( @@ -129,15 +125,13 @@ export async function showConfigurationDialog(storage: SecretStorage) { } -export async function deleteConfiguration(storage: SecretStorage, id: string) { - const config = vscode.workspace.getConfiguration('positron.assistant'); - const existingConfigs = config.get('models') || []; +export async function deleteConfiguration(context: vscode.ExtensionContext, storage: SecretStorage, id: string) { + const existingConfigs: Array = context.globalState.get('positron.assistant.models') || []; const updatedConfigs = existingConfigs.filter(config => config.id !== id); - await config.update( - 'models', - updatedConfigs, - vscode.ConfigurationTarget.Global + await context.globalState.update( + 'positron.assistant.models', + updatedConfigs ); await storage.delete(`apiKey-${id}`); diff --git a/extensions/positron-assistant/src/extension.ts b/extensions/positron-assistant/src/extension.ts index 4fb9b38cb8f..ae0d22e6bfa 100644 --- a/extensions/positron-assistant/src/extension.ts +++ b/extensions/positron-assistant/src/extension.ts @@ -7,9 +7,9 @@ import * as vscode from 'vscode'; import * as positron from 'positron'; import { EncryptedSecretStorage, getModelConfigurations, GlobalSecretStorage, SecretStorage, showConfigurationDialog } from './config'; import { newLanguageModel } from './models'; -import participants from './participants'; import { newCompletionProvider, registerHistoryTracking } from './completion'; import { editsProvider } from './edits'; +import { createParticipants } from './participants'; const hasChatModelsContextKey = 'positron-assistant.hasChatModels'; @@ -32,7 +32,7 @@ async function registerModels(context: vscode.ExtensionContext, storage: SecretS disposeModels(); try { - const modelConfigs = await getModelConfigurations(storage); + const modelConfigs = await getModelConfigurations(context, storage); // Register with Language Model API modelConfigs.filter(config => config.type === 'chat').forEach((config, idx) => { // We need at least one default and one non-default model for the dropdown to appear. @@ -72,6 +72,7 @@ async function registerModels(context: vscode.ExtensionContext, storage: SecretS } function registerParticipants(context: vscode.ExtensionContext) { + const participants = createParticipants(context); Object.keys(participants).forEach(async (key) => { // Register agent with Positron Assistant API // Note: This is an alternative to a `package.json` definition that allows dynamic commands @@ -89,7 +90,7 @@ function registerParticipants(context: vscode.ExtensionContext) { function registerAddModelConfigurationCommand(context: vscode.ExtensionContext, storage: SecretStorage) { context.subscriptions.push( vscode.commands.registerCommand('positron-assistant.addModelConfiguration', () => { - showConfigurationDialog(storage); + showConfigurationDialog(context, storage); }) ); } diff --git a/extensions/positron-assistant/src/participants.ts b/extensions/positron-assistant/src/participants.ts index 10cc1f402d0..da65ea31bbd 100644 --- a/extensions/positron-assistant/src/participants.ts +++ b/extensions/positron-assistant/src/participants.ts @@ -16,6 +16,10 @@ import { defaultHandler } from './commands/default'; const mdDir = `${EXTENSION_ROOT_DIR}/src/md/`; class PositronAssistantParticipant implements positron.ai.ChatParticipant { + readonly _context: vscode.ExtensionContext; + constructor(context: vscode.ExtensionContext) { + this._context = context; + } readonly id = 'positron.positron-assistant'; readonly iconPath = new vscode.ThemeIcon('positron-assistant'); readonly agentData: positron.ai.ChatAgentData = { @@ -73,13 +77,13 @@ class PositronAssistantParticipant implements positron.ai.ChatParticipant { }; readonly welcomeMessageProvider = { - async provideWelcomeMessage(token: vscode.CancellationToken) { + provideWelcomeMessage: async (token: vscode.CancellationToken) => { let welcomeText = await fs.promises.readFile(`${mdDir}/welcome.md`, 'utf8'); const addLanguageModelMessage = vscode.l10n.t('Add a Language Model.'); // Show an extra configuration link if there are no configured models yet - if (getStoredModels().length === 0) { + if (getStoredModels(this._context).length === 0) { const commandUri = vscode.Uri.parse('command:positron.assistant.addModelConfiguration'); welcomeText += `\n\n[${addLanguageModelMessage}](${commandUri})`; } @@ -108,7 +112,9 @@ class PositronAssistantParticipant implements positron.ai.ChatParticipant { dispose(): void { } } -const participants: Record = { - 'positron-assistant': new PositronAssistantParticipant(), -}; -export default participants; +export function createParticipants(context: vscode.ExtensionContext): Record { + return { + 'positron-assistant': new PositronAssistantParticipant(context), + }; +} + From b10af8b1012c4e83677641f036c89723659d08ee Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Wed, 26 Feb 2025 16:34:08 -0800 Subject: [PATCH 11/13] add command to list models --- extensions/positron-assistant/package.json | 8 ++++++-- .../positron-assistant/package.nls.json | 3 ++- extensions/positron-assistant/src/config.ts | 20 +++++++++++++++++++ .../positron-assistant/src/extension.ts | 14 +++++++++++-- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/extensions/positron-assistant/package.json b/extensions/positron-assistant/package.json index 01a1e1cac9f..0163a0dcbd1 100644 --- a/extensions/positron-assistant/package.json +++ b/extensions/positron-assistant/package.json @@ -37,8 +37,12 @@ { "command": "positron-assistant.addModelConfiguration", "title": "%commands.addModelConfiguration.title%", - "category": "%commands.addModelConfiguration.category%", - "enablement": "isDevelopment" + "category": "%commands.category%" + }, + { + "command": "positron-assistant.configureModels", + "title": "%commands.configureModels.title%", + "category": "%commands.category%" } ], "languageModels": [ diff --git a/extensions/positron-assistant/package.nls.json b/extensions/positron-assistant/package.nls.json index 99588e5a7b4..5dbdbbba891 100644 --- a/extensions/positron-assistant/package.nls.json +++ b/extensions/positron-assistant/package.nls.json @@ -2,6 +2,7 @@ "displayName": "Positron Assistant", "description": "Provides default assistant and language models for Positron.", "commands.addModelConfiguration.title": "Add Language Model", - "commands.addModelConfiguration.category": "Positron Assistant", + "commands.configureModels.title": "Configure Language Models", + "commands.category": "Positron Assistant", "configuration.enable.description": "Enable Positron Assistant (experimental)" } diff --git a/extensions/positron-assistant/src/config.ts b/extensions/positron-assistant/src/config.ts index 463d84908eb..c4cbb335581 100644 --- a/extensions/positron-assistant/src/config.ts +++ b/extensions/positron-assistant/src/config.ts @@ -68,6 +68,26 @@ export async function getModelConfigurations(context: vscode.ExtensionContext, s return fullConfigs; } +export async function showModelList(context: vscode.ExtensionContext, storage: SecretStorage) { + // Create a quickpick with all configured models + const modelConfigs = await getModelConfigurations(context, storage); + const quickPick = vscode.window.createQuickPick(); + quickPick.items = [ + ...modelConfigs.map((config) => ({ + label: config.name, + detail: config.model, + description: config.baseUrl, + })), + { + label: vscode.l10n.t('Add New Model...'), + description: vscode.l10n.t('Add a new language model configuration'), + } + ]; + + // Show the quickpick + quickPick.show(); +} + export async function showConfigurationDialog(context: vscode.ExtensionContext, storage: SecretStorage) { // Gather model sources const sources = [...languageModels, ...completionModels].map((provider) => provider.source); diff --git a/extensions/positron-assistant/src/extension.ts b/extensions/positron-assistant/src/extension.ts index ae0d22e6bfa..c23a6d0837f 100644 --- a/extensions/positron-assistant/src/extension.ts +++ b/extensions/positron-assistant/src/extension.ts @@ -5,11 +5,12 @@ import * as vscode from 'vscode'; import * as positron from 'positron'; -import { EncryptedSecretStorage, getModelConfigurations, GlobalSecretStorage, SecretStorage, showConfigurationDialog } from './config'; +import { EncryptedSecretStorage, getModelConfigurations, GlobalSecretStorage, SecretStorage, showConfigurationDialog, showModelList } from './config'; import { newLanguageModel } from './models'; import { newCompletionProvider, registerHistoryTracking } from './completion'; import { editsProvider } from './edits'; import { createParticipants } from './participants'; +import { register } from 'node:module'; const hasChatModelsContextKey = 'positron-assistant.hasChatModels'; @@ -95,6 +96,14 @@ function registerAddModelConfigurationCommand(context: vscode.ExtensionContext, ); } +function registerConfigureModelsCommand(context: vscode.ExtensionContext, storage: SecretStorage) { + context.subscriptions.push( + vscode.commands.registerCommand('positron-assistant.configureModels', () => { + showModelList(context, storage); + }) + ); +} + function registerMappedEditsProvider(context: vscode.ExtensionContext) { context.subscriptions.push( vscode.chat.registerMappedEditsProvider({ pattern: '**/*' }, editsProvider) @@ -115,8 +124,9 @@ function registerAssistant(context: vscode.ExtensionContext) { // Track opened files for completion context registerHistoryTracking(context); - // Configuration modal command + // Commands registerAddModelConfigurationCommand(context, storage); + registerConfigureModelsCommand(context, storage); // Register mapped edits provider registerMappedEditsProvider(context); From 86b90b6b27b8a62224c345e915eba0166879f093 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Wed, 26 Feb 2025 17:00:14 -0800 Subject: [PATCH 12/13] improve quickpick --- extensions/positron-assistant/src/config.ts | 54 ++++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/extensions/positron-assistant/src/config.ts b/extensions/positron-assistant/src/config.ts index c4cbb335581..6b53bfb16bf 100644 --- a/extensions/positron-assistant/src/config.ts +++ b/extensions/positron-assistant/src/config.ts @@ -72,20 +72,62 @@ export async function showModelList(context: vscode.ExtensionContext, storage: S // Create a quickpick with all configured models const modelConfigs = await getModelConfigurations(context, storage); const quickPick = vscode.window.createQuickPick(); - quickPick.items = [ - ...modelConfigs.map((config) => ({ + + // Create sections for chat and completion models + const chatModels = modelConfigs.filter(config => + config.type === 'chat' + ); + const completionModels = modelConfigs.filter(config => + config.type === 'completion' + ); + + const items: Array = [ + { + label: vscode.l10n.t('Chat Models'), + kind: vscode.QuickPickItemKind.Separator + }, + ...chatModels.map((config) => ({ + label: config.name, + detail: config.model + })), + { + label: vscode.l10n.t('Completion Models'), + kind: vscode.QuickPickItemKind.Separator + }, + ...completionModels.map((config) => ({ label: config.name, detail: config.model, - description: config.baseUrl, + description: config.baseUrl })), { - label: vscode.l10n.t('Add New Model...'), + label: '', + kind: vscode.QuickPickItemKind.Separator + }, + { + label: vscode.l10n.t('Add a Language Model'), description: vscode.l10n.t('Add a new language model configuration'), } ]; - // Show the quickpick - quickPick.show(); + vscode.window.showQuickPick(items, { + placeHolder: vscode.l10n.t('Select a language model'), + canPickMany: false, + + }).then(async (selected) => { + if (!selected) { + return; + } + if (selected.description === vscode.l10n.t('Add a new language model configuration')) { + showConfigurationDialog(context, storage); + } else { + const selectedConfig = modelConfigs.find((config) => config.name === selected.label); + if (selectedConfig) { + vscode.window.showInformationMessage( + vscode.l10n.t(`Selected language model: {0}`, selectedConfig.name) + ); + } + } + }); } export async function showConfigurationDialog(context: vscode.ExtensionContext, storage: SecretStorage) { From 1d3d31e5f73048579b528aafad42ec25b75e3752 Mon Sep 17 00:00:00 2001 From: Jonathan McPherson Date: Wed, 26 Feb 2025 17:20:54 -0800 Subject: [PATCH 13/13] explain ourselves --- extensions/positron-assistant/src/config.ts | 17 +++++++++++++++++ extensions/positron-assistant/src/extension.ts | 7 +++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/extensions/positron-assistant/src/config.ts b/extensions/positron-assistant/src/config.ts index 6b53bfb16bf..fdb62f9c34b 100644 --- a/extensions/positron-assistant/src/config.ts +++ b/extensions/positron-assistant/src/config.ts @@ -12,12 +12,20 @@ interface StoredModelConfig extends Omit; get(key: string): Thenable; delete(key: string): Thenable; } +/** + * Implementation of SecretStorage that uses VS Code's secret storage API. + * + * This class should be used in desktop mode to store secrets securely. + */ export class EncryptedSecretStorage implements SecretStorage { constructor(private context: vscode.ExtensionContext) { } store(key: string, value: string): Thenable { @@ -31,6 +39,15 @@ export class EncryptedSecretStorage implements SecretStorage { } } +/** + * Implementation of SecretStorage that uses VS Code's global storage API. + * + * This class stores secrets **insecurely** using VS Code's global storage API. + * It is used in web mode, where there is no durable secret storage. + * + * This class should be replaced with one that uses a secure storage mechanism, + * or just removed altogether when Positron gains secure storage capabilities. + */ export class GlobalSecretStorage implements SecretStorage { constructor(private context: vscode.ExtensionContext) { } store(key: string, value: string): Thenable { diff --git a/extensions/positron-assistant/src/extension.ts b/extensions/positron-assistant/src/extension.ts index c23a6d0837f..19e7ddbedf6 100644 --- a/extensions/positron-assistant/src/extension.ts +++ b/extensions/positron-assistant/src/extension.ts @@ -112,8 +112,11 @@ function registerMappedEditsProvider(context: vscode.ExtensionContext) { function registerAssistant(context: vscode.ExtensionContext) { - // Initialize secret storage. In web mode, use global storage; otherwise, use encrypted storage. - const storage = vscode.env.uiKind === vscode.UIKind.Web ? new GlobalSecretStorage(context) : new EncryptedSecretStorage(context); + // Initialize secret storage. In web mode, we currently need to use global + // secret storage since encrypted storage is not available. + const storage = vscode.env.uiKind === vscode.UIKind.Web ? + new GlobalSecretStorage(context) : + new EncryptedSecretStorage(context); // Register chat participants registerParticipants(context);