use super::{ToolResult, ToolResultDisplay};
use crate::output::ToolDispatchContext;
use serde_json::{Value, json};
pub(super) struct MagiControlContext<'a> {
pub(super) compact_enabled: &'a bool,
}
impl MagiControlContext<'_> {
pub(super) fn run(
&self,
arguments: Value,
context: ToolDispatchContext,
) -> anyhow::Result<ToolResult> {
let object = arguments
.as_object()
.ok_or_else(|| anyhow::anyhow!("magi_control arguments must be an object"))?;
let action = object
.get("action")
.and_then(Value::as_str)
.ok_or_else(|| {
anyhow::anyhow!("magi_control action must be `compact` or `context_usage`")
})?;
if object.keys().any(|key| key != "action" && key != "context") {
anyhow::bail!("magi_control accepts only `action` and optional `context`");
}
match action {
"compact" => {
if !*self.compact_enabled {
anyhow::bail!("magi_control action `compact` is disabled");
}
if let Some(context) = object.get("context") {
let context = context.as_str().ok_or_else(|| {
anyhow::anyhow!("magi_control context must be a nonblank string")
})?;
if context.trim().is_empty() {
anyhow::bail!("magi_control context must be a nonblank string");
}
if context.chars().count() > super::capability::MAGI_CONTROL_CONTEXT_MAX_CHARS {
anyhow::bail!(
"magi_control context exceeds maximum length of {} characters",
super::capability::MAGI_CONTROL_CONTEXT_MAX_CHARS
);
}
}
Ok(ToolResult {
tool_name: crate::tools::contract::tool_name::MAGI_CONTROL.to_string(),
success: true,
content: "compaction requested; execution will continue automatically after compaction".to_string(),
metadata: json!({"action": "compact"}),
display: ToolResultDisplay::default(),
})
}
"context_usage" => {
let usage = context.context_window_usage.ok_or_else(|| {
anyhow::anyhow!("current context-window usage is unavailable")
})?;
let percentage = if usage.max_tokens == 0 {
0
} else {
usize::try_from(
(usage.current_tokens as u128).saturating_mul(100)
/ usage.max_tokens as u128,
)
.unwrap_or(usize::MAX)
};
Ok(ToolResult {
tool_name: crate::tools::contract::tool_name::MAGI_CONTROL.to_string(),
success: true,
content: format!(
"context window: {percentage}% used ({}/{}) tokens",
usage.current_tokens, usage.max_tokens
),
metadata: json!({
"action": "context_usage",
"percentage": percentage,
"current_tokens": usage.current_tokens,
"max_tokens": usage.max_tokens,
}),
display: ToolResultDisplay::default(),
})
}
_ => anyhow::bail!("magi_control action must be `compact` or `context_usage`"),
}
}
}