diff options
| author | Ward Peeters <ward@coding-tech.com> | 2026-07-04 00:29:42 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-04 01:29:42 +0300 |
| commit | d0e333451bd794a419e96f28db925772950ea156 (patch) | |
| tree | 1a6e5d3bd6ac40f8ef454058f069d30202327002 /src/integration/targets.rs | |
| parent | d5521e3d250498df4af552fff83fce3d5ef33810 (diff) | |
feat: add mastracode integration (#788)
* feat: add mastracode integration
refs #337
Co-authored-by: Mastra Code (openai/gpt-5.5) <noreply@mastra.ai>
Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
Diffstat (limited to 'src/integration/targets.rs')
| -rw-r--r-- | src/integration/targets.rs | 112 |
1 files changed, 100 insertions, 12 deletions
diff --git a/src/integration/targets.rs b/src/integration/targets.rs index a47f0dae..2b4c5615 100644 --- a/src/integration/targets.rs +++ b/src/integration/targets.rs @@ -7,15 +7,15 @@ use serde_json::{json, Value}; use super::command::{hook_command, shell_single_quote}; use super::config_edit::{ build_codex_config_with_hooks, build_kimi_config_with_hooks, ensure_command_hook, - ensure_direct_command_hook, ensure_hermes_plugin_enabled, ensure_hooks_object, - ensure_simple_command_hook, hooks_object_if_present, remove_direct_hook_commands, - remove_hermes_plugin_enabled, remove_hook_commands, remove_kimi_config_block, - remove_simple_command_hook, + ensure_direct_command_hook, ensure_flat_command_hook, ensure_hermes_plugin_enabled, + ensure_hooks_object, ensure_simple_command_hook, hooks_object_if_present, + remove_direct_hook_commands, remove_flat_command_hook, remove_hermes_plugin_enabled, + remove_hook_commands, remove_kimi_config_block, remove_simple_command_hook, }; use super::env::{ claude_dir, codex_dir, copilot_dir, cursor_dir, devin_dir, droid_dir, hermes_dir, - hermes_plugin_dir, kilo_dir, kimi_dir, omp_extension_dir, opencode_dir, pi_extension_dir, - qodercli_dir, + hermes_plugin_dir, kilo_dir, kimi_dir, mastracode_dir, omp_extension_dir, opencode_dir, + pi_extension_dir, qodercli_dir, }; use super::file_ops::{ make_executable, remove_dir_all_if_exists, remove_file_if_exists, remove_legacy_bash_hook_file, @@ -25,9 +25,9 @@ use super::types::{ CopilotInstallPaths, CopilotUninstallResult, CursorInstallPaths, CursorUninstallResult, DevinInstallPaths, DevinUninstallResult, DroidInstallPaths, DroidUninstallResult, HermesInstallPaths, HermesUninstallResult, KiloInstallPaths, KiloUninstallResult, - KimiInstallPaths, KimiUninstallResult, OmpInstallPaths, OmpUninstallResult, - OpenCodeInstallPaths, OpenCodeUninstallResult, PiUninstallResult, QodercliInstallPaths, - QodercliUninstallResult, + KimiInstallPaths, KimiUninstallResult, MastracodeInstallPaths, MastracodeUninstallResult, + OmpInstallPaths, OmpUninstallResult, OpenCodeInstallPaths, OpenCodeUninstallResult, + PiUninstallResult, QodercliInstallPaths, QodercliUninstallResult, }; use super::{ CLAUDE_HOOK_ASSET, CLAUDE_HOOK_INSTALL_NAME, CODEX_HOOK_ASSET, CODEX_HOOK_INSTALL_NAME, @@ -38,9 +38,10 @@ use super::{ DROID_HOOK_INSTALL_NAME, DROID_REMOVED_LIFECYCLE_HOOK_EVENTS, HERMES_PLUGIN_INIT_ASSET, HERMES_PLUGIN_INIT_INSTALL_NAME, HERMES_PLUGIN_MANIFEST_ASSET, HERMES_PLUGIN_MANIFEST_INSTALL_NAME, KILO_PLUGIN_ASSET, KILO_PLUGIN_INSTALL_NAME, - KIMI_HOOK_ASSET, KIMI_HOOK_INSTALL_NAME, OMP_EXTENSION_ASSET, OMP_EXTENSION_INSTALL_NAME, - OPENCODE_PLUGIN_ASSET, OPENCODE_PLUGIN_INSTALL_NAME, PI_EXTENSION_ASSET, - PI_EXTENSION_INSTALL_NAME, QODERCLI_HOOK_ASSET, QODERCLI_HOOK_EVENTS, + KIMI_HOOK_ASSET, KIMI_HOOK_INSTALL_NAME, MASTRACODE_HOOK_ASSET, MASTRACODE_HOOK_EVENTS, + MASTRACODE_HOOK_INSTALL_NAME, MASTRACODE_HOOK_TIMEOUT_MS, OMP_EXTENSION_ASSET, + OMP_EXTENSION_INSTALL_NAME, OPENCODE_PLUGIN_ASSET, OPENCODE_PLUGIN_INSTALL_NAME, + PI_EXTENSION_ASSET, PI_EXTENSION_INSTALL_NAME, QODERCLI_HOOK_ASSET, QODERCLI_HOOK_EVENTS, QODERCLI_HOOK_INSTALL_NAME, QODERCLI_REMOVED_LIFECYCLE_HOOK_EVENTS, }; @@ -1106,3 +1107,90 @@ pub(crate) fn uninstall_cursor() -> io::Result<CursorUninstallResult> { updated_hooks, }) } + +pub(crate) fn install_mastracode() -> io::Result<MastracodeInstallPaths> { + let mastracode_home = mastracode_dir()?; + let hook_dir = mastracode_home.join("hooks"); + fs::create_dir_all(&hook_dir)?; + + let hook_path = hook_dir.join(MASTRACODE_HOOK_INSTALL_NAME); + fs::write(&hook_path, MASTRACODE_HOOK_ASSET)?; + make_executable(&hook_path)?; + + let hooks_path = mastracode_home.join("hooks.json"); + let mut hooks_file = if hooks_path.is_file() { + serde_json::from_str::<Value>(&fs::read_to_string(&hooks_path)?).map_err(|err| { + io::Error::other(format!("failed to parse {}: {err}", hooks_path.display())) + })? + } else { + json!({}) + }; + + let hooks = hooks_file.as_object_mut().ok_or_else(|| { + io::Error::other(format!( + "mastracode hooks file at {} must be a JSON object", + hooks_path.display() + )) + })?; + + let quoted_hook_path = shell_single_quote(&hook_path.display().to_string()); + for (event, action) in MASTRACODE_HOOK_EVENTS { + ensure_flat_command_hook( + hooks, + event, + format!("bash {quoted_hook_path} {action}"), + MASTRACODE_HOOK_TIMEOUT_MS, + )?; + } + + fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + + Ok(MastracodeInstallPaths { + hook_path, + hooks_path, + }) +} + +pub(crate) fn uninstall_mastracode() -> io::Result<MastracodeUninstallResult> { + let mastracode_home = mastracode_dir()?; + let hook_path = mastracode_home + .join("hooks") + .join(MASTRACODE_HOOK_INSTALL_NAME); + let hooks_path = mastracode_home.join("hooks.json"); + let mut updated_hooks = false; + + if hooks_path.is_file() { + let mut hooks_file = serde_json::from_str::<Value>(&fs::read_to_string(&hooks_path)?) + .map_err(|err| { + io::Error::other(format!("failed to parse {}: {err}", hooks_path.display())) + })?; + let hooks = hooks_file.as_object_mut().ok_or_else(|| { + io::Error::other(format!( + "mastracode hooks file at {} must be a JSON object", + hooks_path.display() + )) + })?; + + let quoted_hook_path = shell_single_quote(&hook_path.display().to_string()); + for (event, action) in MASTRACODE_HOOK_EVENTS { + updated_hooks |= remove_flat_command_hook( + hooks, + event, + &format!("bash {quoted_hook_path} {action}"), + )?; + } + + if updated_hooks { + fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + } + } + + let removed_hook_file = remove_file_if_exists(&hook_path)?; + + Ok(MastracodeUninstallResult { + hook_path, + hooks_path, + removed_hook_file, + updated_hooks, + }) +} |
