aboutsummaryrefslogtreecommitdiff
path: root/src/integration/targets.rs
diff options
context:
space:
mode:
authorWard Peeters <ward@coding-tech.com>2026-07-04 00:29:42 +0200
committerGitHub <noreply@github.com>2026-07-04 01:29:42 +0300
commitd0e333451bd794a419e96f28db925772950ea156 (patch)
tree1a6e5d3bd6ac40f8ef454058f069d30202327002 /src/integration/targets.rs
parentd5521e3d250498df4af552fff83fce3d5ef33810 (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.rs112
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,
+ })
+}