feat: Enhance OAuth module and OpenRouter client functionality

- Updated OAuth module to include unused imports for better clarity.
- Refactored OpenRouterClient to improve chat functionality and added support for tools in chat requests.
- Modified internet tools (Download, Fetch, Search) to use a more flexible internet mode check.
- Introduced new Bash tools for managing background jobs (BashOutput, BashKill).
- Enhanced workflow tool to parse and execute workflow scripts with arguments.
- Updated status and workflow views to reflect new agent and findings counts.
- Added IPC protocol definitions for client requests and state payloads.
This commit is contained in:
asepharyana
2026-07-11 20:21:59 +07:00
parent c1ad206a00
commit 802d9677ae
42 changed files with 1423 additions and 925 deletions
+47 -6
View File
@@ -1,5 +1,6 @@
use tokio::sync::mpsc;
use crate::dto::chat::message::ChatMessage;
use crate::tool::{all_tools, tool_is_risky};
use super::context::SubagentContext;
use super::event::SubagentEvent;
@@ -21,6 +22,11 @@ pub fn run_subagent(ctx: SubagentContext, tx: mpsc::Sender<SubagentEvent>) -> an
let mut messages: Vec<ChatMessage> = Vec::new();
messages.push(ChatMessage::system(ctx.system_prompt.clone()));
let tool_ctx = crate::tool::ToolCtx::builder()
.session_dir(ctx.session_dir.clone())
.origin(crate::app::state::types::Origin::SubAgent)
.build();
let max_steps = ctx.max_steps.min(MAX_AGENT_STEPS);
for step in 0..max_steps {
let api_key = std::env::var("OPENROUTER_API_KEY").unwrap_or_default();
@@ -55,16 +61,51 @@ pub fn run_subagent(ctx: SubagentContext, tx: mpsc::Sender<SubagentEvent>) -> an
break;
}
} else {
let tools = all_tools();
for tool_name in &tool_calls {
if !ctx.allowed_tools.is_empty() && !ctx.allowed_tools.contains(tool_name) {
let explicitly_allowed = ctx.allowed_tools.contains(tool_name);
let generally_allowed = ctx.allowed_tools.is_empty() || explicitly_allowed;
if !generally_allowed {
let msg = format!("tool '{}' not allowed for this subagent", tool_name);
messages.push(ChatMessage::tool_result("subagent".to_string(), msg));
messages.push(ChatMessage::tool_result(tool_name.clone(), msg.clone()));
let _ = tx.blocking_send(SubagentEvent::ToolResult {
tool: tool_name.clone(),
output: msg,
});
continue;
}
let _ = tx.blocking_send(SubagentEvent::ToolResult {
tool: tool_name.clone(),
output: format!("{} executed", tool_name),
});
if tool_is_risky(tool_name) && !explicitly_allowed {
let msg = format!("risky tool '{}' requires explicit permission; not allowed for this subagent", tool_name);
messages.push(ChatMessage::tool_result(tool_name.clone(), msg.clone()));
let _ = tx.blocking_send(SubagentEvent::ToolResult {
tool: tool_name.clone(),
output: msg,
});
continue;
}
let result = match tools.iter().find(|t| t.name() == *tool_name) {
Some(tool) => tool.run(&tool_ctx, &serde_json::json!({})),
None => Err(anyhow::anyhow!("tool '{}' not found", tool_name)),
};
match result {
Ok(output_text) => {
let _ = tx.blocking_send(SubagentEvent::ToolResult {
tool: tool_name.clone(),
output: output_text,
});
}
Err(e) => {
let msg = format!("tool '{}' failed: {}", tool_name, e);
let _ = tx.blocking_send(SubagentEvent::ToolResult {
tool: tool_name.clone(),
output: msg,
});
}
}
}
let _ = tx.blocking_send(SubagentEvent::StepCompleted {
step,