Fix multiple env var migrations
This commit is contained in:
@@ -88,7 +88,7 @@ const FS_WATCH_LATENCY: Duration = Duration::from_millis(100);
|
||||
/// Extension IDs that are being migrated from hardcoded LLM providers.
|
||||
/// For backwards compatibility, if the user has the corresponding env var set,
|
||||
/// we automatically enable env var reading for these extensions on first install.
|
||||
const LEGACY_LLM_EXTENSION_IDS: &[&str] = &[
|
||||
pub const LEGACY_LLM_EXTENSION_IDS: &[&str] = &[
|
||||
"anthropic",
|
||||
"copilot-chat",
|
||||
"google-ai",
|
||||
@@ -133,7 +133,7 @@ fn migrate_legacy_llm_provider_env_var(manifest: &ExtensionManifest, cx: &mut Ap
|
||||
|
||||
// Check if already enabled in settings
|
||||
let already_enabled = ExtensionSettings::get_global(cx)
|
||||
.allowed_env_vars
|
||||
.allowed_env_var_providers
|
||||
.contains(settings_key.as_ref());
|
||||
|
||||
if already_enabled {
|
||||
@@ -146,7 +146,7 @@ fn migrate_legacy_llm_provider_env_var(manifest: &ExtensionManifest, cx: &mut Ap
|
||||
move |settings, _| {
|
||||
let allowed = settings
|
||||
.extension
|
||||
.allowed_env_vars
|
||||
.allowed_env_var_providers
|
||||
.get_or_insert_with(Vec::new);
|
||||
|
||||
if !allowed
|
||||
@@ -1192,9 +1192,16 @@ impl ExtensionStore {
|
||||
}
|
||||
}
|
||||
|
||||
fs.create_symlink(output_path, extension_source_path)
|
||||
fs.create_symlink(output_path, extension_source_path.clone())
|
||||
.await?;
|
||||
|
||||
// Re-load manifest and run migration before reload so settings are updated before providers are registered
|
||||
let manifest_for_migration =
|
||||
ExtensionManifest::load(fs.clone(), &extension_source_path).await?;
|
||||
this.update(cx, |_this, cx| {
|
||||
migrate_legacy_llm_provider_env_var(&manifest_for_migration, cx);
|
||||
})?;
|
||||
|
||||
this.update(cx, |this, cx| this.reload(None, cx))?.await;
|
||||
this.update(cx, |this, cx| {
|
||||
cx.emit(Event::ExtensionInstalled(extension_id.clone()));
|
||||
|
||||
@@ -19,7 +19,7 @@ pub struct ExtensionSettings {
|
||||
/// The extension language model providers that are allowed to read API keys
|
||||
/// from environment variables. Each entry is in the format
|
||||
/// "extension_id:provider_id:ENV_VAR_NAME".
|
||||
pub allowed_env_vars: HashSet<Arc<str>>,
|
||||
pub allowed_env_var_providers: HashSet<Arc<str>>,
|
||||
}
|
||||
|
||||
impl ExtensionSettings {
|
||||
@@ -64,9 +64,9 @@ impl Settings for ExtensionSettings {
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
allowed_env_vars: content
|
||||
allowed_env_var_providers: content
|
||||
.extension
|
||||
.allowed_env_vars
|
||||
.allowed_env_var_providers
|
||||
.clone()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::ExtensionSettings;
|
||||
use crate::LEGACY_LLM_EXTENSION_IDS;
|
||||
use crate::wasm_host::WasmExtension;
|
||||
use collections::HashSet;
|
||||
|
||||
@@ -69,11 +70,20 @@ impl ExtensionLanguageModelProvider {
|
||||
|
||||
// Build set of allowed env vars for this provider
|
||||
let settings = ExtensionSettings::get_global(cx);
|
||||
let is_legacy_extension =
|
||||
LEGACY_LLM_EXTENSION_IDS.contains(&extension.manifest.id.as_ref());
|
||||
|
||||
let mut allowed_env_vars = HashSet::default();
|
||||
if let Some(env_vars) = auth_config.as_ref().and_then(|c| c.env_vars.as_ref()) {
|
||||
for env_var_name in env_vars {
|
||||
let key = format!("{}:{}", provider_id_string, env_var_name);
|
||||
if settings.allowed_env_vars.contains(key.as_str()) {
|
||||
// For legacy extensions, auto-allow if env var is set (migration will persist this)
|
||||
let env_var_is_set = std::env::var(env_var_name)
|
||||
.map(|v| !v.is_empty())
|
||||
.unwrap_or(false);
|
||||
if settings.allowed_env_var_providers.contains(key.as_str())
|
||||
|| (is_legacy_extension && env_var_is_set)
|
||||
{
|
||||
allowed_env_vars.insert(env_var_name.clone());
|
||||
}
|
||||
}
|
||||
@@ -201,10 +211,18 @@ impl LanguageModelProvider for ExtensionLanguageModelProvider {
|
||||
if let Some(ref env_vars) = auth_config.env_vars {
|
||||
let provider_id_string = self.provider_id_string();
|
||||
let settings = ExtensionSettings::get_global(cx);
|
||||
let is_legacy_extension =
|
||||
LEGACY_LLM_EXTENSION_IDS.contains(&self.extension.manifest.id.as_ref());
|
||||
|
||||
for env_var_name in env_vars {
|
||||
let key = format!("{}:{}", provider_id_string, env_var_name);
|
||||
if settings.allowed_env_vars.contains(key.as_str()) {
|
||||
// For legacy extensions, auto-allow if env var is set
|
||||
let env_var_is_set = std::env::var(env_var_name)
|
||||
.map(|v| !v.is_empty())
|
||||
.unwrap_or(false);
|
||||
if settings.allowed_env_var_providers.contains(key.as_str())
|
||||
|| (is_legacy_extension && env_var_is_set)
|
||||
{
|
||||
if let Ok(value) = std::env::var(env_var_name) {
|
||||
if !value.is_empty() {
|
||||
return true;
|
||||
@@ -474,7 +492,7 @@ impl ExtensionProviderConfigurationView {
|
||||
move |settings, _| {
|
||||
let allowed = settings
|
||||
.extension
|
||||
.allowed_env_vars
|
||||
.allowed_env_var_providers
|
||||
.get_or_insert_with(Vec::new);
|
||||
|
||||
if currently_allowed {
|
||||
|
||||
@@ -1114,6 +1114,7 @@ impl ExtensionImports for WasmState {
|
||||
impl llm_provider::Host for WasmState {
|
||||
async fn get_credential(&mut self, provider_id: String) -> wasmtime::Result<Option<String>> {
|
||||
let extension_id = self.manifest.id.clone();
|
||||
let is_legacy_extension = crate::LEGACY_LLM_EXTENSION_IDS.contains(&extension_id.as_ref());
|
||||
|
||||
// Check if this provider has env vars configured and if the user has allowed any of them
|
||||
let env_vars = self
|
||||
@@ -1131,6 +1132,11 @@ impl llm_provider::Host for WasmState {
|
||||
let settings_key: Arc<str> =
|
||||
format!("{}:{}", full_provider_id, env_var_name).into();
|
||||
|
||||
// For legacy extensions, auto-allow if env var is set
|
||||
let env_var_is_set = env::var(env_var_name)
|
||||
.map(|v| !v.is_empty())
|
||||
.unwrap_or(false);
|
||||
|
||||
let is_allowed = self
|
||||
.on_main_thread({
|
||||
let settings_key = settings_key.clone();
|
||||
@@ -1138,7 +1144,7 @@ impl llm_provider::Host for WasmState {
|
||||
async move {
|
||||
cx.update(|cx| {
|
||||
crate::extension_settings::ExtensionSettings::get_global(cx)
|
||||
.allowed_env_vars
|
||||
.allowed_env_var_providers
|
||||
.contains(&settings_key)
|
||||
})
|
||||
}
|
||||
@@ -1148,7 +1154,7 @@ impl llm_provider::Host for WasmState {
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
|
||||
if is_allowed {
|
||||
if is_allowed || (is_legacy_extension && env_var_is_set) {
|
||||
if let Ok(value) = env::var(env_var_name) {
|
||||
if !value.is_empty() {
|
||||
return Ok(Some(value));
|
||||
@@ -1247,6 +1253,11 @@ impl llm_provider::Host for WasmState {
|
||||
|
||||
// Check if the user has allowed this specific env var
|
||||
let settings_key: Arc<str> = format!("{}:{}:{}", extension_id, provider_id, name).into();
|
||||
let is_legacy_extension = crate::LEGACY_LLM_EXTENSION_IDS.contains(&extension_id.as_ref());
|
||||
|
||||
// For legacy extensions, auto-allow if env var is set
|
||||
let env_var_is_set = env::var(&name).map(|v| !v.is_empty()).unwrap_or(false);
|
||||
|
||||
let is_allowed = self
|
||||
.on_main_thread({
|
||||
let settings_key = settings_key.clone();
|
||||
@@ -1254,7 +1265,7 @@ impl llm_provider::Host for WasmState {
|
||||
async move {
|
||||
cx.update(|cx| {
|
||||
crate::extension_settings::ExtensionSettings::get_global(cx)
|
||||
.allowed_env_vars
|
||||
.allowed_env_var_providers
|
||||
.contains(&settings_key)
|
||||
})
|
||||
}
|
||||
@@ -1264,7 +1275,7 @@ impl llm_provider::Host for WasmState {
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
|
||||
if !is_allowed {
|
||||
if !is_allowed && !(is_legacy_extension && env_var_is_set) {
|
||||
log::debug!(
|
||||
"Extension {} provider {} is not allowed to read env var {}",
|
||||
extension_id,
|
||||
|
||||
@@ -25,7 +25,7 @@ pub struct ExtensionSettingsContent {
|
||||
/// "extension_id:provider_id:ENV_VAR_NAME" (e.g., "google-ai:google-ai:GEMINI_API_KEY").
|
||||
///
|
||||
/// Default: []
|
||||
pub allowed_env_vars: Option<Vec<Arc<str>>>,
|
||||
pub allowed_env_var_providers: Option<Vec<Arc<str>>>,
|
||||
}
|
||||
|
||||
/// A capability for an extension.
|
||||
|
||||
Reference in New Issue
Block a user