From fb5525fc2234a246dfdfc9e0d7ed73c824cbd8a6 Mon Sep 17 00:00:00 2001 From: Mark Jaquith Date: Fri, 11 Sep 2026 16:36:18 -0400 Subject: fix: opencode v2 lifecycle reporting (#3757) * fix: support opencode v2 lifecycle reporting * fix: repair Japanese docs * fix: ignore payload-less OpenCode events * fix: harden opencode v2 integration install and reporting Follow-ups on top of the V2 lifecycle support: - create `cli.json` when OpenCode has no V1 TUI preferences (`tui.json` or `kv.json`) to migrate, instead of only registering into an existing file - settle stalled socket attempts with a plain connect timer, and resend the latest lifecycle state after a failed delivery so the pane cannot get stuck - resolve the OpenCode state directory from `XDG_STATE_HOME` - remove the managed `herdr-opencode` directory on uninstall - document failed executions reporting `blocked`, keep the integration test environment independent of an inherited `XDG_STATE_HOME`, and simplify `reconcileBlockers` to reassign its map --------- Co-authored-by: Jonathan Liebig --- src/integration/env.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src/integration/env.rs') diff --git a/src/integration/env.rs b/src/integration/env.rs index c4ee1c34..48320c72 100644 --- a/src/integration/env.rs +++ b/src/integration/env.rs @@ -127,6 +127,14 @@ pub(crate) fn opencode_dir() -> io::Result { Ok(home_dir()?.join(".config/opencode")) } +pub(crate) fn opencode_state_dir() -> io::Result { + if let Some(value) = std::env::var_os("XDG_STATE_HOME").filter(|value| !value.is_empty()) { + return expand_tilde_path(PathBuf::from(value)).map(|path| path.join("opencode")); + } + + Ok(home_dir()?.join(".local/state/opencode")) +} + pub(crate) fn kilo_dir() -> io::Result { Ok(home_dir()?.join(".config/kilo")) } @@ -248,3 +256,34 @@ pub(crate) fn integration_env_lock() -> IntegrationEnvLock { appdata: std::env::var_os("APPDATA"), } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn opencode_state_dir_defaults_to_local_state() { + let _lock = integration_env_lock(); + let original = std::env::var_os("XDG_STATE_HOME"); + std::env::remove_var("XDG_STATE_HOME"); + let expected = home_dir().unwrap().join(".local/state/opencode"); + assert_eq!(opencode_state_dir().unwrap(), expected); + match original { + Some(value) => std::env::set_var("XDG_STATE_HOME", value), + None => std::env::remove_var("XDG_STATE_HOME"), + } + } + + #[test] + fn opencode_state_dir_honors_xdg_state_home() { + let _lock = integration_env_lock(); + let original = std::env::var_os("XDG_STATE_HOME"); + let xdg = std::env::temp_dir().join("herdr-xdg-state"); + std::env::set_var("XDG_STATE_HOME", &xdg); + assert_eq!(opencode_state_dir().unwrap(), xdg.join("opencode")); + match original { + Some(value) => std::env::set_var("XDG_STATE_HOME", value), + None => std::env::remove_var("XDG_STATE_HOME"), + } + } +} -- cgit v1.2.3