Skip to content

Commit c8fceff

Browse files
committed
Update backend and layout/editor state handling
1 parent 395b6a9 commit c8fceff

11 files changed

Lines changed: 463 additions & 76 deletions

File tree

anycode-backend/src/acp.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,6 +1139,7 @@ pub struct AcpAgent {
11391139
prompt_sender: Option<mpsc::Sender<String>>,
11401140
config_sender: Option<mpsc::Sender<PendingConfigUpdate>>,
11411141
cancel_sender: Arc<tokio::sync::Mutex<Option<mpsc::Sender<()>>>>,
1142+
shutdown_sender: Option<mpsc::Sender<()>>,
11421143
process_handle: Option<tokio::task::JoinHandle<()>>,
11431144
io_handle: Option<tokio::task::JoinHandle<()>>,
11441145
history: Arc<tokio::sync::Mutex<Vec<AcpMessage>>>,
@@ -1174,6 +1175,7 @@ impl AcpAgent {
11741175
prompt_sender: None,
11751176
config_sender: None,
11761177
cancel_sender: Arc::new(tokio::sync::Mutex::new(None)),
1178+
shutdown_sender: None,
11771179
process_handle: None,
11781180
io_handle: None,
11791181
history: Arc::new(tokio::sync::Mutex::new(Vec::new())),
@@ -1203,6 +1205,8 @@ impl AcpAgent {
12031205
let mut cancel_sender_guard = self.cancel_sender.lock().await;
12041206
*cancel_sender_guard = Some(cancel_tx.clone());
12051207
}
1208+
let (shutdown_tx, mut shutdown_rx) = mpsc::channel::<()>(1);
1209+
self.shutdown_sender = Some(shutdown_tx);
12061210

12071211
let (bootstrap_tx, bootstrap_rx) = oneshot::channel::<Result<SessionBootstrap>>();
12081212

@@ -1250,8 +1254,21 @@ impl AcpAgent {
12501254
self.connection = None;
12511255

12521256
let process_handle = tokio::spawn(async move {
1253-
let _ = child.wait().await;
1254-
debug!("ACP agent process ended");
1257+
tokio::select! {
1258+
result = child.wait() => {
1259+
if let Err(err) = result {
1260+
debug!("ACP agent process wait failed: {}", err);
1261+
}
1262+
debug!("ACP agent process ended");
1263+
}
1264+
_ = shutdown_rx.recv() => {
1265+
if let Err(err) = child.kill().await {
1266+
debug!("ACP agent process kill failed: {}", err);
1267+
}
1268+
let _ = child.wait().await;
1269+
debug!("ACP agent process stopped manually");
1270+
}
1271+
}
12551272
});
12561273
self.process_handle = Some(process_handle);
12571274

@@ -1967,8 +1984,11 @@ impl AcpAgent {
19671984

19681985
pub async fn stop(&mut self) {
19691986
self.ready.store(false, Ordering::SeqCst);
1987+
if let Some(shutdown_tx) = self.shutdown_sender.take() {
1988+
let _ = shutdown_tx.send(()).await;
1989+
}
19701990
if let Some(handle) = self.process_handle.take() {
1971-
handle.abort();
1991+
let _ = handle.await;
19721992
}
19731993
if let Some(handle) = self.io_handle.take() {
19741994
handle.abort();
@@ -2182,6 +2202,13 @@ impl AcpManager {
21822202
}
21832203
}
21842204

2205+
pub async fn stop_all(&mut self) {
2206+
let agent_ids: Vec<String> = self.agents.keys().cloned().collect();
2207+
for agent_id in agent_ids {
2208+
self.stop_agent(&agent_id).await;
2209+
}
2210+
}
2211+
21852212
/// Cancel current prompt for agent by agent_id.
21862213
pub async fn cancel_prompt(&self, agent_id: &str) -> Result<()> {
21872214
if let Some(agent) = self.agents.get(agent_id) {

anycode-backend/src/app_state.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@ pub struct TerminalData {
3737
pub buffer: Arc<Mutex<VecDeque<String>>>,
3838
}
3939

40+
impl AppState {
41+
pub async fn shutdown(&self) {
42+
self.lsp_manager.lock().await.stop_all().await;
43+
self.acp_manager.lock().await.stop_all().await;
44+
45+
let terminal_handles = self
46+
.terminals
47+
.lock()
48+
.await
49+
.values()
50+
.cloned()
51+
.collect::<Vec<_>>();
52+
53+
for terminal in terminal_handles {
54+
let _ = terminal.terminal.kill().await;
55+
}
56+
}
57+
}
58+
4059
#[macro_export]
4160
macro_rules! error_ack {
4261
($ack:expr, $path:expr, $msg:expr $(, $args:expr)*) => {{

anycode-backend/src/lsp.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,10 @@ impl Lsp {
162162
debug!("lsp process wait done");
163163
}
164164
_ = kill_recv.recv() => {
165-
child.kill().await.expect("kill failed");
165+
if let Err(err) = child.kill().await {
166+
debug!("lsp process kill failed: {}", err);
167+
}
168+
let _ = child.wait().await;
166169
debug!("lsp process killed manually");
167170
}
168171
}
@@ -831,4 +834,11 @@ impl LspManager {
831834
info!("stopped lsp: {}", lang);
832835
}
833836
}
837+
838+
pub async fn stop_all(&mut self) {
839+
let langs: Vec<String> = self.lang2lsp.keys().cloned().collect();
840+
for lang in langs {
841+
self.stop(&lang).await;
842+
}
843+
}
834844
}

anycode-backend/src/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ async fn main() -> Result<()> {
255255
let acp_fs_lsp = state.lsp_manager.clone();
256256
let acp_fs_config = state.config.clone();
257257

258-
let (layer, io) = SocketIo::builder().with_state(state).build_layer();
258+
let (layer, io) = SocketIo::builder().with_state(state.clone()).build_layer();
259259
let cors = ServiceBuilder::new()
260260
.layer(CorsLayer::permissive())
261261
.layer(layer);
@@ -343,5 +343,7 @@ async fn main() -> Result<()> {
343343
})
344344
.await?;
345345

346+
state.shutdown().await;
347+
346348
Ok(())
347349
}

anycode-backend/src/terminal.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ impl Terminal {
137137
}
138138
Some(_) = kill_rx.recv() => {
139139
let _ = child.kill();
140+
let _ = child.wait();
140141
break;
141142
}
142143
else => break,

anycode/App.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ const App: React.FC = () => {
4949
wsRef,
5050
isConnected,
5151
diffEnabled,
52-
onFileClosed: (fileId: string) => {
53-
const node = fileTree.findNodeByPath(fileTree.fileTree, fileId);
54-
if (node) fileTree.clearFileSelection();
55-
},
5652
});
5753

5854
const terminals = useTerminals({ wsRef, isConnected });
@@ -181,23 +177,27 @@ const App: React.FC = () => {
181177
search.startSearch(pattern);
182178
};
183179

180+
const resolveEditorPaneId = useCallback(() => {
181+
return layoutActionsRef.current?.ensureEditorPanel(editors.activeEditorPaneId);
182+
}, [editors]);
183+
184184
const handleOpenFile = useCallback((path: string, line?: number, column?: number) => {
185-
const paneId = layoutActionsRef.current?.ensureEditorPanel();
185+
const paneId = resolveEditorPaneId();
186186
if (!paneId) return;
187187
editors.openFile(path, line, column, paneId);
188-
}, [editors]);
188+
}, [editors, resolveEditorPaneId]);
189189

190190
const handleOpenFileDiff = useCallback((path: string, line?: number, column?: number) => {
191-
const paneId = layoutActionsRef.current?.ensureEditorPanel();
191+
const paneId = resolveEditorPaneId();
192192
if (!paneId) return;
193193
editors.openFileDiff(path, line, column, paneId);
194-
}, [editors]);
194+
}, [editors, resolveEditorPaneId]);
195195

196196
const handleSelectFile = useCallback((fileId: string) => {
197-
const paneId = layoutActionsRef.current?.ensureEditorPanel();
197+
const paneId = resolveEditorPaneId();
198198
if (!paneId) return;
199199
editors.setActiveFileId(fileId, paneId);
200-
}, [editors]);
200+
}, [editors, resolveEditorPaneId]);
201201

202202
const handleSearchResultClick = (filePath: string, match: SearchMatch) => {
203203
handleOpenFile(filePath, match.line, match.column);

anycode/components/layout/Layout.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144

145145
.layout .dv-split-view-container .dv-view {
146146
padding: 0 !important;
147-
overflow: visible !important;
147+
overflow: hidden !important;
148148
background-color: transparent !important;
149149
box-sizing: border-box !important;
150150
}

0 commit comments

Comments
 (0)