acp: Support specifying settings for extensions (#43177)
This allows you to specify default_model and default_mode for ACP
extensions, e.g.
```
"auggie": {
"default_model": "gpt-5",
"default_mode": "default",
"type": "extension"
},
```
Release Notes:
- Added support for specifying settings for ACP extensions
(`default_mode`, `default_model`)
This commit is contained in:
@@ -141,3 +141,9 @@ pub(crate) mod m_2025_11_12 {
|
||||
|
||||
pub(crate) use settings::SETTINGS_PATTERNS;
|
||||
}
|
||||
|
||||
pub(crate) mod m_2025_11_20 {
|
||||
mod settings;
|
||||
|
||||
pub(crate) use settings::SETTINGS_PATTERNS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use tree_sitter::{Query, QueryMatch};
|
||||
|
||||
use crate::MigrationPatterns;
|
||||
|
||||
pub const SETTINGS_PATTERNS: MigrationPatterns = &[(
|
||||
SETTINGS_AGENT_SERVERS_CUSTOM_PATTERN,
|
||||
migrate_custom_agent_settings,
|
||||
)];
|
||||
|
||||
const SETTINGS_AGENT_SERVERS_CUSTOM_PATTERN: &str = r#"(document
|
||||
(object
|
||||
(pair
|
||||
key: (string (string_content) @agent-servers)
|
||||
value: (object
|
||||
(pair
|
||||
key: (string (string_content) @server-name)
|
||||
value: (object) @server-settings
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(#eq? @agent-servers "agent_servers")
|
||||
)"#;
|
||||
|
||||
fn migrate_custom_agent_settings(
|
||||
contents: &str,
|
||||
mat: &QueryMatch,
|
||||
query: &Query,
|
||||
) -> Option<(Range<usize>, String)> {
|
||||
let server_name_index = query.capture_index_for_name("server-name")?;
|
||||
let server_name = mat.nodes_for_capture_index(server_name_index).next()?;
|
||||
let server_name_text = &contents[server_name.byte_range()];
|
||||
|
||||
if matches!(server_name_text, "gemini" | "claude" | "codex") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let server_settings_index = query.capture_index_for_name("server-settings")?;
|
||||
let server_settings = mat.nodes_for_capture_index(server_settings_index).next()?;
|
||||
|
||||
let mut column = None;
|
||||
|
||||
// Parse the server settings to check what keys it contains
|
||||
let mut cursor = server_settings.walk();
|
||||
for child in server_settings.children(&mut cursor) {
|
||||
if child.kind() == "pair" {
|
||||
if let Some(key_node) = child.child_by_field_name("key") {
|
||||
if let (None, Some(quote_content)) = (column, key_node.child(0)) {
|
||||
column = Some(quote_content.start_position().column);
|
||||
}
|
||||
if let Some(string_content) = key_node.child(1) {
|
||||
let key = &contents[string_content.byte_range()];
|
||||
match key {
|
||||
// If it already has a type key, don't modify it
|
||||
"type" => return None,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the type key at the beginning of the object
|
||||
let start = server_settings.start_byte() + 1;
|
||||
let indent = " ".repeat(column.unwrap_or(12));
|
||||
|
||||
Some((
|
||||
start..start,
|
||||
format!(
|
||||
r#"
|
||||
{indent}"type": "custom","#
|
||||
),
|
||||
))
|
||||
}
|
||||
@@ -219,6 +219,10 @@ pub fn migrate_settings(text: &str) -> Result<Option<String>> {
|
||||
migrations::m_2025_11_12::SETTINGS_PATTERNS,
|
||||
&SETTINGS_QUERY_2025_11_12,
|
||||
),
|
||||
MigrationType::TreeSitter(
|
||||
migrations::m_2025_11_20::SETTINGS_PATTERNS,
|
||||
&SETTINGS_QUERY_2025_11_20,
|
||||
),
|
||||
];
|
||||
run_migrations(text, migrations)
|
||||
}
|
||||
@@ -341,6 +345,10 @@ define_query!(
|
||||
SETTINGS_QUERY_2025_11_12,
|
||||
migrations::m_2025_11_12::SETTINGS_PATTERNS
|
||||
);
|
||||
define_query!(
|
||||
SETTINGS_QUERY_2025_11_20,
|
||||
migrations::m_2025_11_20::SETTINGS_PATTERNS
|
||||
);
|
||||
|
||||
// custom query
|
||||
static EDIT_PREDICTION_SETTINGS_MIGRATION_QUERY: LazyLock<Query> = LazyLock::new(|| {
|
||||
@@ -1192,6 +1200,63 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_custom_agent_server_settings_migration() {
|
||||
assert_migrate_settings_with_migrations(
|
||||
&[MigrationType::TreeSitter(
|
||||
migrations::m_2025_11_20::SETTINGS_PATTERNS,
|
||||
&SETTINGS_QUERY_2025_11_20,
|
||||
)],
|
||||
r#"{
|
||||
"agent_servers": {
|
||||
"gemini": {
|
||||
"default_model": "gemini-1.5-pro"
|
||||
},
|
||||
"claude": {},
|
||||
"codex": {},
|
||||
"my-custom-agent": {
|
||||
"command": "/path/to/agent",
|
||||
"args": ["--foo"],
|
||||
"default_model": "my-model"
|
||||
},
|
||||
"already-migrated-agent": {
|
||||
"type": "custom",
|
||||
"command": "/path/to/agent"
|
||||
},
|
||||
"future-extension-agent": {
|
||||
"type": "extension",
|
||||
"default_model": "ext-model"
|
||||
}
|
||||
}
|
||||
}"#,
|
||||
Some(
|
||||
r#"{
|
||||
"agent_servers": {
|
||||
"gemini": {
|
||||
"default_model": "gemini-1.5-pro"
|
||||
},
|
||||
"claude": {},
|
||||
"codex": {},
|
||||
"my-custom-agent": {
|
||||
"type": "custom",
|
||||
"command": "/path/to/agent",
|
||||
"args": ["--foo"],
|
||||
"default_model": "my-model"
|
||||
},
|
||||
"already-migrated-agent": {
|
||||
"type": "custom",
|
||||
"command": "/path/to/agent"
|
||||
},
|
||||
"future-extension-agent": {
|
||||
"type": "extension",
|
||||
"default_model": "ext-model"
|
||||
}
|
||||
}
|
||||
}"#,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_version_fields() {
|
||||
assert_migrate_settings(
|
||||
|
||||
Reference in New Issue
Block a user