feat(client): emit ChatEvent::ToolCall with approval metadata
ToolCall events carry call_id, name, args, needs_approval — agent layer uses these to route through the permission/approval flow.
This commit is contained in:
@@ -11,6 +11,8 @@ use super::project::ProjectContext;
|
||||
|
||||
/// Events produced during a chat turn, for the TUI to render.
|
||||
pub enum ChatEvent {
|
||||
/// A client-side tool call that needs execution (possibly with approval).
|
||||
ToolCall { call_id: String, name: String, args: String, needs_approval: bool },
|
||||
ToolStart { name: String, detail: String },
|
||||
ToolDone { name: String, success: bool },
|
||||
Status(String),
|
||||
@@ -21,6 +23,8 @@ pub enum ChatEvent {
|
||||
pub struct ChatResponse {
|
||||
pub text: String,
|
||||
pub events: Vec<ChatEvent>,
|
||||
pub input_tokens: u32,
|
||||
pub output_tokens: u32,
|
||||
}
|
||||
|
||||
fn truncate_args(args_json: &str) -> String {
|
||||
@@ -150,26 +154,29 @@ impl CodeSession {
|
||||
return Ok(ChatResponse {
|
||||
text: d.full_text,
|
||||
events,
|
||||
input_tokens: d.input_tokens,
|
||||
output_tokens: d.output_tokens,
|
||||
});
|
||||
}
|
||||
Some(ServerMessage {
|
||||
payload: Some(server_message::Payload::ToolCall(tc)),
|
||||
}) => {
|
||||
if tc.is_local {
|
||||
// TODO: approval flow through TUI
|
||||
events.push(ChatEvent::ToolStart {
|
||||
// Emit ToolCall event — agent handles approval + execution
|
||||
events.push(ChatEvent::ToolCall {
|
||||
call_id: tc.call_id.clone(),
|
||||
name: tc.name.clone(),
|
||||
detail: truncate_args(&tc.args_json),
|
||||
args: tc.args_json.clone(),
|
||||
needs_approval: tc.needs_approval,
|
||||
});
|
||||
|
||||
// Execute immediately for now — approval is handled
|
||||
// by the agent layer which wraps this method.
|
||||
// When approval flow is active, the agent will call
|
||||
// execute + send_tool_result separately.
|
||||
let result =
|
||||
super::tools::execute(&tc.name, &tc.args_json, &self.project_path);
|
||||
|
||||
events.push(ChatEvent::ToolDone {
|
||||
name: tc.name.clone(),
|
||||
success: true,
|
||||
});
|
||||
|
||||
self.tx
|
||||
.send(ClientMessage {
|
||||
payload: Some(client_message::Payload::ToolResult(ToolResult {
|
||||
@@ -205,6 +212,8 @@ impl CodeSession {
|
||||
return Ok(ChatResponse {
|
||||
text: "Session ended by server.".into(),
|
||||
events,
|
||||
input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
});
|
||||
}
|
||||
Some(_) => continue,
|
||||
|
||||
Reference in New Issue
Block a user