generated from nhcarrigan/template
feat: expose modelOverrides setting in ConfigSidebar
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
@@ -46,6 +48,9 @@ pub struct ClaudeStartOptions {
|
||||
|
||||
#[serde(default)]
|
||||
pub auto_memory_directory: Option<String>,
|
||||
|
||||
#[serde(default)]
|
||||
pub model_overrides: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -192,6 +197,9 @@ pub struct HikariConfig {
|
||||
|
||||
#[serde(default)]
|
||||
pub auto_memory_directory: Option<String>,
|
||||
|
||||
#[serde(default)]
|
||||
pub model_overrides: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl Default for HikariConfig {
|
||||
@@ -242,6 +250,7 @@ impl Default for HikariConfig {
|
||||
include_git_instructions: true,
|
||||
enable_claudeai_mcp_servers: true,
|
||||
auto_memory_directory: None,
|
||||
model_overrides: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -392,6 +401,7 @@ mod tests {
|
||||
assert!(config.include_git_instructions);
|
||||
assert!(config.enable_claudeai_mcp_servers);
|
||||
assert!(config.auto_memory_directory.is_none());
|
||||
assert!(config.model_overrides.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -442,6 +452,10 @@ mod tests {
|
||||
include_git_instructions: false,
|
||||
enable_claudeai_mcp_servers: false,
|
||||
auto_memory_directory: Some("/custom/memory".to_string()),
|
||||
model_overrides: Some(HashMap::from([(
|
||||
"claude-opus-4-6".to_string(),
|
||||
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-4-6-v1".to_string(),
|
||||
)])),
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&config).unwrap();
|
||||
@@ -466,6 +480,12 @@ mod tests {
|
||||
deserialized.auto_memory_directory,
|
||||
Some("/custom/memory".to_string())
|
||||
);
|
||||
assert!(deserialized.model_overrides.is_some());
|
||||
let overrides = deserialized.model_overrides.unwrap();
|
||||
assert_eq!(
|
||||
overrides.get("claude-opus-4-6").map(String::as_str),
|
||||
Some("arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-4-6-v1")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+128
-12
@@ -291,10 +291,39 @@ impl WslBridge {
|
||||
cmd.arg("--worktree");
|
||||
}
|
||||
|
||||
// Pass auto-memory directory via settings if specified
|
||||
if let Some(ref dir) = options.auto_memory_directory {
|
||||
if !dir.is_empty() {
|
||||
cmd.args(["--settings", &format!(r#"{{"autoMemoryDirectory":"{}"}}"#, dir)]);
|
||||
// Pass combined settings via --settings flag if any settings are specified
|
||||
{
|
||||
let has_memory_dir = options
|
||||
.auto_memory_directory
|
||||
.as_deref()
|
||||
.map(|d| !d.is_empty())
|
||||
.unwrap_or(false);
|
||||
let has_overrides = options
|
||||
.model_overrides
|
||||
.as_ref()
|
||||
.map(|m| !m.is_empty())
|
||||
.unwrap_or(false);
|
||||
|
||||
if has_memory_dir || has_overrides {
|
||||
let mut settings = serde_json::Map::new();
|
||||
if let Some(ref dir) = options.auto_memory_directory {
|
||||
if !dir.is_empty() {
|
||||
settings.insert(
|
||||
"autoMemoryDirectory".to_string(),
|
||||
serde_json::Value::String(dir.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(ref overrides) = options.model_overrides {
|
||||
if !overrides.is_empty() {
|
||||
if let Ok(val) = serde_json::to_value(overrides) {
|
||||
settings.insert("modelOverrides".to_string(), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Ok(settings_json) = serde_json::to_string(&settings) {
|
||||
cmd.args(["--settings", &settings_json]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,14 +470,40 @@ impl WslBridge {
|
||||
claude_cmd.push_str(" --worktree");
|
||||
}
|
||||
|
||||
// Pass auto-memory directory via settings if specified
|
||||
if let Some(ref dir) = options.auto_memory_directory {
|
||||
if !dir.is_empty() {
|
||||
let escaped_dir = dir.replace('\'', "'\\''");
|
||||
claude_cmd.push_str(&format!(
|
||||
" --settings '{{\"autoMemoryDirectory\":\"{}\"}}'",
|
||||
escaped_dir
|
||||
));
|
||||
// Pass combined settings via --settings flag if any settings are specified
|
||||
{
|
||||
let has_memory_dir = options
|
||||
.auto_memory_directory
|
||||
.as_deref()
|
||||
.map(|d| !d.is_empty())
|
||||
.unwrap_or(false);
|
||||
let has_overrides = options
|
||||
.model_overrides
|
||||
.as_ref()
|
||||
.map(|m| !m.is_empty())
|
||||
.unwrap_or(false);
|
||||
|
||||
if has_memory_dir || has_overrides {
|
||||
let mut settings = serde_json::Map::new();
|
||||
if let Some(ref dir) = options.auto_memory_directory {
|
||||
if !dir.is_empty() {
|
||||
settings.insert(
|
||||
"autoMemoryDirectory".to_string(),
|
||||
serde_json::Value::String(dir.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(ref overrides) = options.model_overrides {
|
||||
if !overrides.is_empty() {
|
||||
if let Ok(val) = serde_json::to_value(overrides) {
|
||||
settings.insert("modelOverrides".to_string(), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Ok(settings_json) = serde_json::to_string(&settings) {
|
||||
let escaped = settings_json.replace('\'', "'\\''");
|
||||
claude_cmd.push_str(&format!(" --settings '{}'", escaped));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3075,4 +3130,65 @@ mod tests {
|
||||
let dir = "";
|
||||
assert!(dir.is_empty(), "Empty directory should be skipped");
|
||||
}
|
||||
|
||||
/// Build the combined settings JSON for both memory directory and model overrides (for testing)
|
||||
#[cfg(test)]
|
||||
fn build_combined_settings_arg(
|
||||
memory_dir: Option<&str>,
|
||||
model_overrides: Option<&std::collections::HashMap<String, String>>,
|
||||
) -> String {
|
||||
let mut settings = serde_json::Map::new();
|
||||
if let Some(dir) = memory_dir {
|
||||
if !dir.is_empty() {
|
||||
settings.insert(
|
||||
"autoMemoryDirectory".to_string(),
|
||||
serde_json::Value::String(dir.to_string()),
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(overrides) = model_overrides {
|
||||
if !overrides.is_empty() {
|
||||
if let Ok(val) = serde_json::to_value(overrides) {
|
||||
settings.insert("modelOverrides".to_string(), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
serde_json::to_string(&settings).unwrap_or_default()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_e2e_combined_settings_memory_only() {
|
||||
let result = build_combined_settings_arg(Some("/custom/dir"), None);
|
||||
assert_eq!(result, r#"{"autoMemoryDirectory":"/custom/dir"}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_e2e_combined_settings_overrides_only() {
|
||||
let mut overrides = std::collections::HashMap::new();
|
||||
overrides.insert(
|
||||
"claude-opus-4-6".to_string(),
|
||||
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-4-6-v1".to_string(),
|
||||
);
|
||||
let result = build_combined_settings_arg(None, Some(&overrides));
|
||||
assert!(result.contains("modelOverrides"));
|
||||
assert!(result.contains("claude-opus-4-6"));
|
||||
assert!(result.contains("arn:aws:bedrock"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_e2e_combined_settings_both_fields() {
|
||||
let mut overrides = std::collections::HashMap::new();
|
||||
overrides.insert("claude-opus-4-6".to_string(), "custom-model-id".to_string());
|
||||
let result = build_combined_settings_arg(Some("/mem/dir"), Some(&overrides));
|
||||
assert!(result.contains("autoMemoryDirectory"));
|
||||
assert!(result.contains("modelOverrides"));
|
||||
assert!(result.contains("/mem/dir"));
|
||||
assert!(result.contains("custom-model-id"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_e2e_combined_settings_empty_produces_empty_object() {
|
||||
let result = build_combined_settings_arg(Some(""), None);
|
||||
assert_eq!(result, "{}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user