feat(tui): implement agent turn engine for background processing and enhance input handling

This commit is contained in:
asepharyana
2026-07-20 10:55:09 +07:00
parent da2ed6da25
commit 792695b65a
31 changed files with 603 additions and 153 deletions
@@ -46,7 +46,13 @@ impl Tool for LspCompletion {
let line = args.get("line").and_then(|v| v.as_i64()).unwrap_or(0);
let character = args.get("character").and_then(|v| v.as_i64()).unwrap_or(0);
let manager = ctx.lsp_manager.lock().unwrap();
let manager = match ctx.lsp_manager.lock() {
Ok(g) => g,
Err(poisoned) => {
tracing::error!("LSP manager mutex poisoned, recovering");
poisoned.into_inner()
}
};
if let Some(client) = manager.get_client(&language) {
let result = client.send_request("textDocument/completion", &json!({
"textDocument": { "uri": format!("file://{}", path) },
+7 -1
View File
@@ -46,7 +46,13 @@ impl Tool for LspConnect {
.map(|arr| arr.iter().filter_map(|v| v.as_str().map(String::from)).collect())
.unwrap_or_default();
let mut manager = ctx.lsp_manager.lock().unwrap();
let mut manager = match ctx.lsp_manager.lock() {
Ok(g) => g,
Err(poisoned) => {
tracing::error!("LSP manager mutex poisoned, recovering");
poisoned.into_inner()
}
};
manager.start(&language, &command, &extra_args)?;
Ok(format!("Connected LSP for '{language}'"))
@@ -46,7 +46,13 @@ impl Tool for LspDefinition {
let line = args.get("line").and_then(|v| v.as_i64()).unwrap_or(0);
let character = args.get("character").and_then(|v| v.as_i64()).unwrap_or(0);
let manager = ctx.lsp_manager.lock().unwrap();
let manager = match ctx.lsp_manager.lock() {
Ok(g) => g,
Err(poisoned) => {
tracing::error!("LSP manager mutex poisoned, recovering");
poisoned.into_inner()
}
};
if let Some(client) = manager.get_client(&language) {
let result = client.send_request("textDocument/definition", &json!({
"textDocument": { "uri": format!("file://{}", path) },
@@ -36,7 +36,13 @@ impl Tool for LspDiagnostics {
let language = crate::tools::arg_str(args, "language")?;
let path = crate::tools::arg_str(args, "path")?;
let manager = ctx.lsp_manager.lock().unwrap();
let manager = match ctx.lsp_manager.lock() {
Ok(g) => g,
Err(poisoned) => {
tracing::error!("LSP manager mutex poisoned, recovering");
poisoned.into_inner()
}
};
if let Some(client) = manager.get_client(&language) {
let result = client.send_request("textDocument/diagnostic", &json!({
"textDocument": { "uri": format!("file://{}", path) }
@@ -30,7 +30,13 @@ impl Tool for LspDisconnect {
fn run(&self, ctx: &ToolCtx, args: &Value) -> Result<String> {
let language = crate::tools::arg_str(args, "language")?;
let _manager = ctx.lsp_manager.lock().unwrap();
let _manager = match ctx.lsp_manager.lock() {
Ok(g) => g,
Err(poisoned) => {
tracing::error!("LSP manager mutex poisoned, recovering");
poisoned.into_inner()
}
};
Ok(format!("Disconnected LSP for '{language}'"))
}
}
+7 -1
View File
@@ -46,7 +46,13 @@ impl Tool for LspHover {
let line = args.get("line").and_then(|v| v.as_i64()).unwrap_or(0);
let character = args.get("character").and_then(|v| v.as_i64()).unwrap_or(0);
let manager = ctx.lsp_manager.lock().unwrap();
let manager = match ctx.lsp_manager.lock() {
Ok(g) => g,
Err(poisoned) => {
tracing::error!("LSP manager mutex poisoned, recovering");
poisoned.into_inner()
}
};
if let Some(client) = manager.get_client(&language) {
let result = client.send_request("textDocument/hover", &json!({
"textDocument": { "uri": format!("file://{}", path) },
@@ -46,7 +46,13 @@ impl Tool for LspReferences {
let line = args.get("line").and_then(|v| v.as_i64()).unwrap_or(0);
let character = args.get("character").and_then(|v| v.as_i64()).unwrap_or(0);
let manager = ctx.lsp_manager.lock().unwrap();
let manager = match ctx.lsp_manager.lock() {
Ok(g) => g,
Err(poisoned) => {
tracing::error!("LSP manager mutex poisoned, recovering");
poisoned.into_inner()
}
};
if let Some(client) = manager.get_client(&language) {
let result = client.send_request("textDocument/references", &json!({
"textDocument": { "uri": format!("file://{}", path) },