fix: revert the change for unexpected change from ui/goose2 work (#9098)

This commit is contained in:
Lifei Zhou
2026-05-08 19:19:15 +10:00
committed by GitHub
parent c822d1ed82
commit 2db5e58ec7
21 changed files with 207 additions and 201 deletions
+7
View File
@@ -811,6 +811,13 @@ impl Agent {
let results = futures::future::join_all(extension_futures).await;
// Persist once after all extensions are loaded
if results.iter().any(|r| r.success) {
if let Err(e) = self.persist_extension_state(&session_id).await {
warn!("Failed to persist extension state after bulk load: {}", e);
}
}
results
}
@@ -36,7 +36,7 @@ pub static PLATFORM_EXTENSIONS: Lazy<HashMap<&'static str, PlatformExtensionDef>
display_name: "Analyze",
description:
"Analyze code structure with tree-sitter: directory overviews, file details, symbol call graphs",
default_enabled: false,
default_enabled: true,
unprefixed_tools: true,
hidden: false,
client_factory: |ctx| Box::new(analyze::AnalyzeClient::new(ctx).unwrap()),
@@ -64,7 +64,7 @@ pub static PLATFORM_EXTENSIONS: Lazy<HashMap<&'static str, PlatformExtensionDef>
display_name: "Apps",
description:
"Create and manage custom Goose apps through chat. Apps are HTML/CSS/JavaScript and run in sandboxed windows.",
default_enabled: false,
default_enabled: true,
unprefixed_tools: false,
hidden: false,
client_factory: |ctx| Box::new(apps::AppsManagerClient::new(ctx).unwrap()),
@@ -105,7 +105,7 @@ pub static PLATFORM_EXTENSIONS: Lazy<HashMap<&'static str, PlatformExtensionDef>
name: summon::EXTENSION_NAME,
display_name: "Summon",
description: "Load knowledge and delegate tasks to subagents",
default_enabled: false,
default_enabled: true,
unprefixed_tools: true,
hidden: false,
client_factory: |ctx| Box::new(summon::SummonClient::new(ctx).unwrap()),
@@ -182,7 +182,7 @@ pub static PLATFORM_EXTENSIONS: Lazy<HashMap<&'static str, PlatformExtensionDef>
display_name: "Top Of Mind",
description:
"Inject custom context into every turn via GOOSE_MOIM_MESSAGE_TEXT and GOOSE_MOIM_MESSAGE_FILE environment variables",
default_enabled: false,
default_enabled: true,
unprefixed_tools: false,
hidden: false,
client_factory: |ctx| Box::new(tom::TomClient::new(ctx).unwrap()),
+2 -4
View File
@@ -1994,12 +1994,10 @@ extensions:
)
.unwrap();
// User config (higher priority / write target) has already migrated, then disables
// developer and adds a new extension.
// User config (higher priority / write target) disables developer and adds a new extension
std::fs::write(
local_file.path(),
r#"
extensions_on_demand_migration: true
extensions:
developer:
enabled: false
@@ -2024,7 +2022,7 @@ extensions:
let values = config.load()?;
let extensions = values.get("extensions").unwrap().as_mapping().unwrap();
// developer should be disabled (user config overrides system after migration)
// developer should be disabled (user config overrides system)
let dev = extensions.get("developer").unwrap().as_mapping().unwrap();
assert!(!dev.get("enabled").unwrap().as_bool().unwrap());
// Fields from the system config should be preserved via merge
-23
View File
@@ -13,13 +13,8 @@ pub const DEFAULT_EXTENSION_DESCRIPTION: &str = "";
pub const DEFAULT_DISPLAY_NAME: &str = "Developer";
const EXTENSIONS_CONFIG_KEY: &str = "extensions";
fn default_extension_enabled() -> bool {
true
}
#[derive(Debug, Deserialize, Serialize, Clone, ToSchema)]
pub struct ExtensionEntry {
#[serde(default = "default_extension_enabled")]
pub enabled: bool,
#[serde(flatten)]
pub config: ExtensionConfig,
@@ -215,22 +210,4 @@ mod tests {
assert!(!is_extension_available(&unknown_platform));
assert!(is_extension_available(&builtin));
}
#[test]
fn test_extension_entry_defaults_missing_enabled_to_true() {
let value = serde_yaml::from_str(
r#"
type: stdio
name: github
description: GitHub tools
cmd: npx
args: []
"#,
)
.unwrap();
let entry: ExtensionEntry = serde_yaml::from_value(value).unwrap();
assert!(entry.enabled);
}
}
+1 -108
View File
@@ -114,18 +114,10 @@ mod tests {
assert!(changed);
let extensions_key = serde_yaml::Value::String(EXTENSIONS_CONFIG_KEY.to_string());
assert!(config.contains_key(&extensions_key));
let extensions = config.get(&extensions_key).unwrap().as_mapping().unwrap();
for (key, value) in extensions {
let key = key.as_str().unwrap();
let def = PLATFORM_EXTENSIONS.get(key).unwrap();
let entry: ExtensionEntry = serde_yaml::from_value(value.clone()).unwrap();
assert_eq!(entry.enabled, def.default_enabled);
}
}
#[test]
fn test_migrate_platform_extensions_refreshes_metadata_without_changing_enabled() {
fn test_migrate_platform_extensions_preserves_enabled_state() {
let mut config = Mapping::new();
let mut extensions = Mapping::new();
let todo_entry = ExtensionEntry {
@@ -157,105 +149,6 @@ mod tests {
let todo_entry: ExtensionEntry = serde_yaml::from_value(todo_value.clone()).unwrap();
assert!(!todo_entry.enabled);
match todo_entry.config {
ExtensionConfig::Platform {
description,
display_name,
..
} => {
assert_ne!(description, "old description");
assert_ne!(display_name.as_deref(), Some("Old Name"));
}
other => panic!("expected platform extension, got {other:?}"),
}
}
#[test]
fn test_migrate_platform_extensions_preserves_existing_enabled_values() {
let mut config = Mapping::new();
let mut extensions = Mapping::new();
let analyze_entry = ExtensionEntry {
config: ExtensionConfig::Platform {
name: "analyze".to_string(),
description: "Analyze code structure".to_string(),
display_name: Some("Analyze".to_string()),
bundled: Some(true),
available_tools: Vec::new(),
},
enabled: true,
};
let developer_entry = ExtensionEntry {
config: ExtensionConfig::Platform {
name: "developer".to_string(),
description: "Write and edit files, and execute shell commands".to_string(),
display_name: Some("Developer".to_string()),
bundled: Some(true),
available_tools: Vec::new(),
},
enabled: false,
};
let custom_developer_entry = ExtensionEntry {
config: ExtensionConfig::Stdio {
name: "developer".to_string(),
description: "Custom user developer tools".to_string(),
cmd: "custom-developer".to_string(),
args: Vec::new(),
envs: Default::default(),
env_keys: Vec::new(),
timeout: Some(300),
bundled: None,
available_tools: Vec::new(),
},
enabled: true,
};
extensions.insert(
serde_yaml::Value::String("analyze".to_string()),
serde_yaml::to_value(&analyze_entry).unwrap(),
);
extensions.insert(
serde_yaml::Value::String("developer".to_string()),
serde_yaml::to_value(&developer_entry).unwrap(),
);
extensions.insert(
serde_yaml::Value::String("custom-developer".to_string()),
serde_yaml::to_value(&custom_developer_entry).unwrap(),
);
config.insert(
serde_yaml::Value::String(EXTENSIONS_CONFIG_KEY.to_string()),
serde_yaml::Value::Mapping(extensions),
);
assert!(run_migrations(&mut config));
let extensions_key = serde_yaml::Value::String(EXTENSIONS_CONFIG_KEY.to_string());
let extensions = config.get(&extensions_key).unwrap().as_mapping().unwrap();
let analyze: ExtensionEntry = serde_yaml::from_value(
extensions
.get(serde_yaml::Value::String("analyze".to_string()))
.unwrap()
.clone(),
)
.unwrap();
let developer: ExtensionEntry = serde_yaml::from_value(
extensions
.get(serde_yaml::Value::String("developer".to_string()))
.unwrap()
.clone(),
)
.unwrap();
let custom_developer: ExtensionEntry = serde_yaml::from_value(
extensions
.get(serde_yaml::Value::String("custom-developer".to_string()))
.unwrap()
.clone(),
)
.unwrap();
assert!(analyze.enabled);
assert!(!developer.enabled);
assert!(custom_developer.enabled);
}
#[test]
+5 -5
View File
@@ -244,7 +244,7 @@ pub async fn run_config_mcp<C: Connection>() {
let mcp = McpFixture::new(expected_session_id.clone()).await;
let config_yaml = format!(
"GOOSE_MODEL: {TEST_MODEL}\nGOOSE_PROVIDER: openai\nextensions_on_demand_migration: true\nextensions:\n mcp-fixture:\n enabled: true\n type: streamable_http\n name: mcp-fixture\n description: MCP fixture\n uri: \"{}\"\n",
"GOOSE_MODEL: {TEST_MODEL}\nGOOSE_PROVIDER: openai\nextensions:\n mcp-fixture:\n enabled: true\n type: streamable_http\n name: mcp-fixture\n description: MCP fixture\n uri: \"{}\"\n",
mcp.url
);
fs::write(temp_dir.path().join(CONFIG_YAML_NAME), config_yaml).unwrap();
@@ -294,7 +294,7 @@ pub async fn run_config_mcp<C: Connection>() {
pub async fn run_fs_read_text_file_true<C: Connection>() {
let temp_dir = tempfile::tempdir().unwrap();
let config_yaml = format!(
"GOOSE_MODEL: {TEST_MODEL}\nGOOSE_PROVIDER: openai\nextensions_on_demand_migration: true\nextensions:\n developer:\n enabled: true\n type: platform\n name: developer\n description: Developer\n display_name: Developer\n bundled: true\n available_tools: []\n"
"GOOSE_MODEL: {TEST_MODEL}\nGOOSE_PROVIDER: openai\nextensions:\n developer:\n enabled: true\n type: platform\n name: developer\n description: Developer\n display_name: Developer\n bundled: true\n available_tools: []\n"
);
fs::write(temp_dir.path().join(CONFIG_YAML_NAME), config_yaml).unwrap();
@@ -463,7 +463,7 @@ pub async fn run_load_mode<C: Connection>() {
let mcp = McpFixture::new(expected_session_id.clone()).await;
let config_yaml = format!(
"GOOSE_MODEL: {TEST_MODEL}\nGOOSE_PROVIDER: openai\nextensions_on_demand_migration: true\nextensions:\n mcp-fixture:\n enabled: true\n type: streamable_http\n name: mcp-fixture\n description: MCP fixture\n uri: \"{}\"\n",
"GOOSE_MODEL: {TEST_MODEL}\nGOOSE_PROVIDER: openai\nextensions:\n mcp-fixture:\n enabled: true\n type: streamable_http\n name: mcp-fixture\n description: MCP fixture\n uri: \"{}\"\n",
mcp.url
);
fs::write(temp_dir.path().join(CONFIG_YAML_NAME), config_yaml).unwrap();
@@ -703,7 +703,7 @@ async fn run_mode_set_impl<C: Connection>(via: SetModeVia) {
let mcp = McpFixture::new(expected_session_id.clone()).await;
let config_yaml = format!(
"GOOSE_MODEL: {TEST_MODEL}\nGOOSE_PROVIDER: openai\nextensions_on_demand_migration: true\nextensions:\n mcp-fixture:\n enabled: true\n type: streamable_http\n name: mcp-fixture\n description: MCP fixture\n uri: \"{}\"\n",
"GOOSE_MODEL: {TEST_MODEL}\nGOOSE_PROVIDER: openai\nextensions:\n mcp-fixture:\n enabled: true\n type: streamable_http\n name: mcp-fixture\n description: MCP fixture\n uri: \"{}\"\n",
mcp.url
);
fs::write(temp_dir.path().join(CONFIG_YAML_NAME), config_yaml).unwrap();
@@ -1305,7 +1305,7 @@ pub async fn run_prompt_skill<C: Connection>() {
.await;
let config = TestConnectionConfig {
builtins: vec!["summon".to_string(), "skills".to_string()],
builtins: vec!["summon".to_string()],
cwd: Some(cwd),
..Default::default()
};
@@ -523,7 +523,6 @@ fn test_developer_fs_requests_use_acp_session_id() {
// gpt-5-nano routes to the Responses API; use a Chat Completions
// model so the canned SSE fixtures are parsed correctly.
current_model: "gpt-4.1".to_string(),
builtins: vec!["developer".to_string()],
read_text_file: Some(Arc::new(move |req| {
*seen_session_id_clone.lock().unwrap() = Some(req.session_id.0.to_string());
Ok(agent_client_protocol::schema::ReadTextFileResponse::new(