From 266d6f6d876ab3eb020b88ef6caee0f91776db37 Mon Sep 17 00:00:00 2001 From: akbash Date: Wed, 16 Sep 2026 23:22:37 +0300 Subject: fix: respect opencode tui.json registrations (#4250) refs #4240 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig --- src/integration/opencode_config.rs | 72 ++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 10 deletions(-) (limited to 'src/integration/opencode_config.rs') diff --git a/src/integration/opencode_config.rs b/src/integration/opencode_config.rs index b062365b..888efa13 100644 --- a/src/integration/opencode_config.rs +++ b/src/integration/opencode_config.rs @@ -10,12 +10,17 @@ use super::config_file::{check_config_target, write_config}; const TUI_CONFIG_NAME: &str = "tui.jsonc"; -pub(crate) fn tui_config_path(config_dir: &Path) -> PathBuf { - config_dir.join(TUI_CONFIG_NAME) +fn tui_config_paths(config_dir: &Path) -> [PathBuf; 2] { + [ + config_dir.join(TUI_CONFIG_NAME), + config_dir.join("tui.json"), + ] } pub(crate) fn validate_tui_plugin_config(config_dir: &Path) -> io::Result<()> { - validate_plugin_config(&tui_config_path(config_dir), "plugin")?; + for path in tui_config_paths(config_dir) { + validate_plugin_config(&path, "plugin")?; + } validate_plugin_config(&config_dir.join("cli.json"), "plugins") } @@ -37,7 +42,13 @@ fn validate_plugin_config(config_path: &Path, key: &str) -> io::Result<()> { } pub(crate) fn add_tui_plugin(config_dir: &Path, plugin_spec: &str) -> io::Result { - add_plugin(tui_config_path(config_dir), "plugin", plugin_spec) + for path in tui_config_paths(config_dir) { + if plugin_is_configured(&path, "plugin", plugin_spec) { + return Ok(path); + } + } + // Keep tui.json absent on fresh installs so OpenCode can migrate its settings. + add_plugin(config_dir.join(TUI_CONFIG_NAME), "plugin", plugin_spec) } pub(crate) fn add_cli_plugin( @@ -98,8 +109,21 @@ fn add_plugin(config_path: PathBuf, key: &str, plugin_spec: &str) -> io::Result< Ok(config_path) } -pub(crate) fn remove_tui_plugin(config_dir: &Path, plugin_spec: &str) -> io::Result { - remove_plugin(&tui_config_path(config_dir), "plugin", plugin_spec) +pub(crate) fn remove_tui_plugin(config_dir: &Path, plugin_spec: &str) -> io::Result> { + let mut updated = Vec::new(); + let mut errors = Vec::new(); + for path in tui_config_paths(config_dir) { + match remove_plugin(&path, "plugin", plugin_spec) { + Ok(true) => updated.push(path), + Ok(false) => {} + Err(err) => errors.push(err.to_string()), + } + } + if errors.is_empty() { + Ok(updated) + } else { + Err(io::Error::other(errors.join("; "))) + } } pub(crate) fn remove_cli_plugin(config_dir: &Path, plugin_spec: &str) -> io::Result { @@ -143,7 +167,9 @@ fn remove_plugin(config_path: &Path, key: &str, plugin_spec: &str) -> io::Result } pub(crate) fn tui_plugin_is_configured(config_dir: &Path, plugin_spec: &str) -> bool { - plugin_is_configured(&tui_config_path(config_dir), "plugin", plugin_spec) + tui_config_paths(config_dir) + .iter() + .any(|path| plugin_is_configured(path, "plugin", plugin_spec)) } pub(crate) fn cli_plugin_is_configured(config_dir: &Path, plugin_spec: &str) -> bool { @@ -323,7 +349,10 @@ mod tests { ]) ); - assert!(remove_tui_plugin(&dir, "./herdr-tui-state.js").unwrap()); + assert_eq!( + remove_tui_plugin(&dir, "./herdr-tui-state.js").unwrap(), + vec![config_path.clone()] + ); let removed_content = fs::read_to_string(&config_path).unwrap(); assert!(removed_content.contains("// Keep this comment.")); let removed = parse_config(&config_path); @@ -364,13 +393,33 @@ mod tests { let dir = unique_dir(); let config_path = add_tui_plugin(&dir, "./herdr-tui-state.js").unwrap(); - assert!(remove_tui_plugin(&dir, "./herdr-tui-state.js").unwrap()); + assert_eq!( + remove_tui_plugin(&dir, "./herdr-tui-state.js").unwrap(), + vec![config_path.clone()] + ); assert!(config_path.is_file()); assert_eq!(parse_config(&config_path), json!({})); fs::remove_dir_all(dir).unwrap(); } + #[test] + fn configured_tui_plugin_accepts_json_registration() { + let dir = unique_dir(); + fs::write( + dir.join("tui.json"), + r#"{"plugin":["./herdr-tui-session.js"]}"#, + ) + .unwrap(); + + let configured = tui_plugin_is_configured(&dir, "./herdr-tui-session.js"); + fs::remove_dir_all(dir).unwrap(); + assert!( + configured, + "OpenCode loads plugin registrations from tui.json" + ); + } + #[test] fn configured_tui_plugin_accepts_option_tuple() { let dir = unique_dir(); @@ -381,7 +430,10 @@ mod tests { .unwrap(); assert!(tui_plugin_is_configured(&dir, "./herdr-tui-state.js")); - assert!(remove_tui_plugin(&dir, "./herdr-tui-state.js").unwrap()); + assert_eq!( + remove_tui_plugin(&dir, "./herdr-tui-state.js").unwrap(), + vec![dir.join(TUI_CONFIG_NAME)] + ); fs::remove_dir_all(dir).unwrap(); } -- cgit v1.2.3