use crate::state::AppState;
use super::{rpc_tool_result, tool_result_error, tool_result_json};
pub(super) async fn execute(
state: &AppState,
name: &str,
args: &serde_json::Value,
workspace_id: &str,
) -> Option<serde_json::Value> {
let result = match name {
"subscribe_to_events" => {
let agent_id = args.get("agentId").and_then(|v| v.as_str()).unwrap_or("");
let agent_name = args.get("agentName").and_then(|v| v.as_str()).unwrap_or("");
let event_types: Vec<crate::events::AgentEventType> = args
.get("eventTypes")
.and_then(|v| v.as_array())
.map(|arr| {
arr.iter()
.filter_map(|v| v.as_str())
.filter_map(crate::events::AgentEventType::from_str)
.collect()
})
.unwrap_or_default();
let subscription_id = uuid::Uuid::new_v4().to_string();
let subscription = crate::events::EventSubscription {
id: subscription_id.clone(),
agent_id: agent_id.to_string(),
agent_name: agent_name.to_string(),
event_types,
exclude_self: true,
one_shot: false,
wait_group_id: None,
priority: 0,
};
state.event_bus.subscribe(subscription).await;
tool_result_json(&serde_json::json!({
"success": true,
"subscriptionId": subscription_id
}))
}
"unsubscribe_from_events" => {
let subscription_id = args
.get("subscriptionId")
.and_then(|v| v.as_str())
.unwrap_or("");
state.event_bus.unsubscribe(subscription_id).await;
tool_result_json(&serde_json::json!({
"success": true,
"subscriptionId": subscription_id
}))
}
"create_board" => match rpc_tool_result(
state,
"kanban.createBoard",
serde_json::json!({
"workspaceId": workspace_id,
"name": args.get("name").and_then(|v| v.as_str()).unwrap_or("Board"),
"columns": args.get("columns").cloned(),
}),
)
.await
{
Ok(result) => {
let board = result.get("board").cloned().unwrap_or_default();
let columns = board
.get("columns")
.and_then(|value| value.as_array())
.cloned()
.unwrap_or_default()
.into_iter()
.map(|column| {
serde_json::json!({
"id": column.get("id").cloned().unwrap_or_default(),
"name": column.get("name").cloned().unwrap_or_default()
})
})
.collect::<Vec<_>>();
tool_result_json(&serde_json::json!({
"boardId": board.get("id").cloned().unwrap_or_default(),
"name": board.get("name").cloned().unwrap_or_default(),
"columns": columns
}))
}
Err(error) => tool_result_error(&error),
},
"list_boards" => match rpc_tool_result(
state,
"kanban.listBoards",
serde_json::json!({ "workspaceId": workspace_id }),
)
.await
{
Ok(result) => {
let boards = result
.get("boards")
.cloned()
.unwrap_or_else(|| serde_json::json!([]));
tool_result_json(&boards)
}
Err(error) => tool_result_error(&error),
},
"get_board" => match rpc_tool_result(
state,
"kanban.getBoard",
serde_json::json!({
"boardId": args.get("boardId").and_then(|v| v.as_str()).unwrap_or("")
}),
)
.await
{
Ok(result) => tool_result_json(&result),
Err(error) => tool_result_error(&error),
},
"create_card" => match rpc_tool_result(
state,
"kanban.createCard",
serde_json::json!({
"workspaceId": workspace_id,
"boardId": args.get("boardId").cloned(),
"columnId": args.get("columnId").cloned(),
"title": args.get("title").and_then(|v| v.as_str()).unwrap_or(""),
"description": args.get("description").cloned(),
"priority": args.get("priority").cloned(),
"labels": args.get("labels").cloned(),
}),
)
.await
{
Ok(result) => {
let card = result
.get("card")
.cloned()
.unwrap_or_else(|| serde_json::json!({}));
tool_result_json(&card)
}
Err(error) => tool_result_error(&error),
},
"move_card" => match rpc_tool_result(
state,
"kanban.moveCard",
serde_json::json!({
"cardId": args.get("cardId").and_then(|v| v.as_str()).unwrap_or(""),
"targetColumnId": args.get("targetColumnId").and_then(|v| v.as_str()).unwrap_or(""),
"position": args.get("position").cloned(),
}),
)
.await
{
Ok(result) => {
let card = result
.get("card")
.cloned()
.unwrap_or_else(|| serde_json::json!({}));
tool_result_json(&card)
}
Err(error) => tool_result_error(&error),
},
"update_card" => match rpc_tool_result(
state,
"kanban.updateCard",
serde_json::json!({
"cardId": args.get("cardId").and_then(|v| v.as_str()).unwrap_or(""),
"title": args.get("title").cloned(),
"description": args.get("description").cloned(),
"comment": args.get("comment").cloned(),
"priority": args.get("priority").cloned(),
"labels": args.get("labels").cloned(),
}),
)
.await
{
Ok(result) => {
let card = result
.get("card")
.cloned()
.unwrap_or_else(|| serde_json::json!({}));
tool_result_json(&card)
}
Err(error) => tool_result_error(&error),
},
"delete_card" => match rpc_tool_result(
state,
"kanban.deleteCard",
serde_json::json!({
"cardId": args.get("cardId").and_then(|v| v.as_str()).unwrap_or("")
}),
)
.await
{
Ok(result) => tool_result_json(&result),
Err(error) => tool_result_error(&error),
},
"create_column" => match rpc_tool_result(
state,
"kanban.createColumn",
serde_json::json!({
"boardId": args.get("boardId").and_then(|v| v.as_str()).unwrap_or(""),
"name": args.get("name").and_then(|v| v.as_str()).unwrap_or(""),
"color": args.get("color").cloned(),
}),
)
.await
{
Ok(result) => {
let board = result.get("board").cloned().unwrap_or_default();
let column = board
.get("columns")
.and_then(|value| value.as_array())
.and_then(|columns| columns.last())
.cloned()
.unwrap_or_default();
tool_result_json(&serde_json::json!({
"columnId": column.get("id").cloned().unwrap_or_default(),
"name": column.get("name").cloned().unwrap_or_default(),
"position": column.get("position").cloned().unwrap_or_default()
}))
}
Err(error) => tool_result_error(&error),
},
"delete_column" => match rpc_tool_result(
state,
"kanban.deleteColumn",
serde_json::json!({
"boardId": args.get("boardId").and_then(|v| v.as_str()).unwrap_or(""),
"columnId": args.get("columnId").and_then(|v| v.as_str()).unwrap_or(""),
"deleteCards": args.get("deleteCards").cloned(),
}),
)
.await
{
Ok(result) => tool_result_json(&serde_json::json!({
"deleted": result.get("deleted").cloned().unwrap_or(serde_json::json!(false)),
"columnId": result.get("columnId").cloned().unwrap_or_default(),
"cardsDeleted": result.get("cardsDeleted").cloned().unwrap_or(serde_json::json!(0)),
"cardsMoved": result.get("cardsMoved").cloned().unwrap_or(serde_json::json!(0)),
})),
Err(error) => tool_result_error(&error),
},
"search_cards" => match rpc_tool_result(
state,
"kanban.searchCards",
serde_json::json!({
"workspaceId": workspace_id,
"query": args.get("query").and_then(|v| v.as_str()).unwrap_or(""),
"boardId": args.get("boardId").cloned(),
}),
)
.await
{
Ok(result) => {
let cards = result
.get("cards")
.cloned()
.unwrap_or_else(|| serde_json::json!([]));
tool_result_json(&cards)
}
Err(error) => tool_result_error(&error),
},
"list_cards_by_column" => match rpc_tool_result(
state,
"kanban.listCardsByColumn",
serde_json::json!({
"workspaceId": workspace_id,
"columnId": args.get("columnId").and_then(|v| v.as_str()).unwrap_or(""),
"boardId": args.get("boardId").cloned(),
}),
)
.await
{
Ok(result) => tool_result_json(&result),
Err(error) => tool_result_error(&error),
},
"decompose_tasks" => match rpc_tool_result(
state,
"kanban.decomposeTasks",
serde_json::json!({
"workspaceId": workspace_id,
"boardId": args.get("boardId").cloned(),
"columnId": args.get("columnId").cloned(),
"tasks": args.get("tasks").cloned().unwrap_or_else(|| serde_json::json!([])),
}),
)
.await
{
Ok(result) => tool_result_json(&result),
Err(error) => tool_result_error(&error),
},
_ => return None,
};
Some(result)
}