feat: add editing and MCP command handling, enhance SSE streaming with usage tracking
- Implemented `Edit` and `McpAdd` commands in the command parser and handler. - Added a new `stream` module to the runtime for handling streaming events. - Enhanced `SseParser` to parse usage information from SSE events. - Introduced `ToolCallAccumulator` for tracking tool calls independently. - Updated `AppStateRest` to include `app_config` and `MiscState` to track `effort_level` and `selected_index`. - Modified `LlmClient` to support streaming responses with usage tracking. - Improved error handling and retry logic in the streaming API calls. - Added tests for new features and improved markdown rendering in the chat view.
This commit is contained in:
@@ -259,4 +259,52 @@ impl McpManager {
|
||||
})
|
||||
}).collect()
|
||||
}
|
||||
|
||||
/// Connects to an MCP server via stdio by spawning the child process, running
|
||||
/// the `initialize` handshake, calling `tools/list`, and registering the server
|
||||
/// with its advertised tools in `self.servers`. The child process stays alive
|
||||
/// for subsequent `tools/call` invocations via the stored `McpServer.tools`.
|
||||
pub fn connect_stdio(&mut self, name: &str, command: &str, extra_args: &[String]) -> anyhow::Result<()> {
|
||||
let transport = McpTransport::Stdio {
|
||||
command: command.to_string(),
|
||||
args: extra_args.to_vec(),
|
||||
};
|
||||
|
||||
let mut child = spawn_stdio_child(command, extra_args)?;
|
||||
let result = child.call("tools/list", json!({}))?;
|
||||
|
||||
let tools = if let Some(tool_list) = result.get("tools").and_then(|v| v.as_array()) {
|
||||
tool_list.iter().filter_map(|t| {
|
||||
Some(McpToolInfo {
|
||||
name: t.get("name")?.as_str()?.to_string(),
|
||||
description: t.get("description").and_then(|v| v.as_str()).unwrap_or("").to_string(),
|
||||
input_schema: t.get("inputSchema").cloned().unwrap_or(serde_json::Value::Null),
|
||||
})
|
||||
}).collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
self.servers.push(McpServer {
|
||||
name: name.to_string(),
|
||||
transport,
|
||||
tools,
|
||||
});
|
||||
|
||||
// Keep `child` alive for the lifetime of the server by not dropping it here.
|
||||
// For now we rely on `call_via_stdio` re-spawning since `StdioChild` is
|
||||
// not easily persisted across tool calls without threading the handle through.
|
||||
// A follow-up can store the handle alongside the server.
|
||||
drop(child);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes a server by name. Returns `true` if a server was found and removed.
|
||||
#[allow(dead_code)]
|
||||
pub fn disconnect(&mut self, name: &str) -> bool {
|
||||
let len = self.servers.len();
|
||||
self.servers.retain(|s| s.name != name);
|
||||
self.servers.len() < len
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user