Skip to content

Commit 8beb1b8

Browse files
fix(team): read provider().model() not feature model for sub-agent default
load_main_model_from_config() read config.model() — the feature-config model from settings.json (e.g. 'openai/glm-5.1-fast') — instead of config.provider().model() — the /setup-saved active provider model (e.g. 'custom/openclaw'). The latter is what the main session actually connects with and what the status bar shows. Sub-agents inherited the wrong model, which might not exist on the custom endpoint. Fix: use config.provider().model() so sub-agents default to the same provider that the user's main session is connected to. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 7dc422d commit 8beb1b8

27 files changed

Lines changed: 1450 additions & 586 deletions

rust/crates/runtime/src/lsp_client/dispatch.rs

Lines changed: 150 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ impl super::LspRegistry {
4747
let language = if lsp_action == LspAction::WorkspaceSymbols {
4848
// Try to find any connected server for workspace symbols
4949
let inner = self.inner.lock().expect("lsp registry lock poisoned");
50-
inner.servers.keys().next().cloned()
50+
inner
51+
.servers
52+
.keys()
53+
.next()
54+
.cloned()
5155
.ok_or_else(|| "no LSP servers available for workspace symbols".to_owned())?
5256
} else {
5357
let p = path.ok_or("path is required for this LSP action")?;
@@ -160,159 +164,189 @@ impl super::LspRegistry {
160164
let hover = process.hover(path, line, character).await;
161165
hover.map(|opt| {
162166
opt.map_or_else(
163-
|| serde_json::json!({
164-
"action": "hover",
165-
"path": path,
166-
"line": line,
167-
"character": character,
168-
"language": language,
169-
"status": "no_result",
170-
}),
171-
|h| serde_json::json!({
172-
"action": "hover",
173-
"path": path,
174-
"line": line,
175-
"character": character,
176-
"language": language,
177-
"status": "ok",
178-
"result": h,
179-
}),
167+
|| {
168+
serde_json::json!({
169+
"action": "hover",
170+
"path": path,
171+
"line": line,
172+
"character": character,
173+
"language": language,
174+
"status": "no_result",
175+
})
176+
},
177+
|h| {
178+
serde_json::json!({
179+
"action": "hover",
180+
"path": path,
181+
"line": line,
182+
"character": character,
183+
"language": language,
184+
"status": "ok",
185+
"result": h,
186+
})
187+
},
180188
)
181189
})
182190
}
183191
LspAction::Definition => {
184192
let locations = process.goto_definition(path, line, character).await;
185-
locations.map(|locs| serde_json::json!({
186-
"action": "definition",
187-
"path": path,
188-
"line": line,
189-
"character": character,
190-
"language": language,
191-
"status": "ok",
192-
"locations": locs,
193-
}))
193+
locations.map(|locs| {
194+
serde_json::json!({
195+
"action": "definition",
196+
"path": path,
197+
"line": line,
198+
"character": character,
199+
"language": language,
200+
"status": "ok",
201+
"locations": locs,
202+
})
203+
})
194204
}
195205
LspAction::References => {
196206
let locations = process.references(path, line, character).await;
197-
locations.map(|locs| serde_json::json!({
198-
"action": "references",
199-
"path": path,
200-
"line": line,
201-
"character": character,
202-
"language": language,
203-
"status": "ok",
204-
"locations": locs,
205-
}))
207+
locations.map(|locs| {
208+
serde_json::json!({
209+
"action": "references",
210+
"path": path,
211+
"line": line,
212+
"character": character,
213+
"language": language,
214+
"status": "ok",
215+
"locations": locs,
216+
})
217+
})
206218
}
207219
LspAction::Completion => {
208220
let items = process.completion(path, line, character).await;
209-
items.map(|completions| serde_json::json!({
210-
"action": "completion",
211-
"path": path,
212-
"line": line,
213-
"character": character,
214-
"language": language,
215-
"status": "ok",
216-
"items": completions,
217-
}))
221+
items.map(|completions| {
222+
serde_json::json!({
223+
"action": "completion",
224+
"path": path,
225+
"line": line,
226+
"character": character,
227+
"language": language,
228+
"status": "ok",
229+
"items": completions,
230+
})
231+
})
218232
}
219233
LspAction::Symbols => {
220234
let symbols = process.document_symbols(path).await;
221-
symbols.map(|syms| serde_json::json!({
222-
"action": "symbols",
223-
"path": path,
224-
"line": line,
225-
"character": character,
226-
"language": language,
227-
"status": "ok",
228-
"symbols": syms,
229-
}))
235+
symbols.map(|syms| {
236+
serde_json::json!({
237+
"action": "symbols",
238+
"path": path,
239+
"line": line,
240+
"character": character,
241+
"language": language,
242+
"status": "ok",
243+
"symbols": syms,
244+
})
245+
})
230246
}
231247
LspAction::Format => {
232248
let edits = process.format(path).await;
233-
edits.map(|text_edits| serde_json::json!({
234-
"action": "format",
235-
"path": path,
236-
"line": line,
237-
"character": character,
238-
"language": language,
239-
"status": "ok",
240-
"edits": text_edits,
241-
}))
249+
edits.map(|text_edits| {
250+
serde_json::json!({
251+
"action": "format",
252+
"path": path,
253+
"line": line,
254+
"character": character,
255+
"language": language,
256+
"status": "ok",
257+
"edits": text_edits,
258+
})
259+
})
242260
}
243261
LspAction::CodeAction => {
244262
let end_line = if line > 0 { Some(line) } else { None };
245263
let end_character = if character > 0 { Some(character) } else { None };
246-
let actions = process.code_action(path, line, character, end_line, end_character, None).await;
247-
actions.map(|acts| serde_json::json!({
248-
"action": "code_action",
249-
"path": path,
250-
"line": 0,
251-
"character": 0,
252-
"end_line": end_line,
253-
"end_character": end_character,
254-
"language": language,
255-
"status": "ok",
256-
"actions": acts,
257-
}))
264+
let actions = process
265+
.code_action(path, line, character, end_line, end_character, None)
266+
.await;
267+
actions.map(|acts| {
268+
serde_json::json!({
269+
"action": "code_action",
270+
"path": path,
271+
"line": 0,
272+
"character": 0,
273+
"end_line": end_line,
274+
"end_character": end_character,
275+
"language": language,
276+
"status": "ok",
277+
"actions": acts,
278+
})
279+
})
258280
}
259281
LspAction::Rename => {
260-
let new_name = _query.ok_or_else(|| LspProcessError::InvalidRequest("new_name required for rename".into()))?;
282+
let new_name = _query.ok_or_else(|| {
283+
LspProcessError::InvalidRequest("new_name required for rename".into())
284+
})?;
261285
let rename_result = process.rename(path, line, character, new_name).await;
262-
rename_result.map(|r| serde_json::json!({
263-
"action": "rename",
264-
"path": path,
265-
"line": line,
266-
"character": character,
267-
"language": language,
268-
"status": "ok",
269-
"result": r,
270-
}))
286+
rename_result.map(|r| {
287+
serde_json::json!({
288+
"action": "rename",
289+
"path": path,
290+
"line": line,
291+
"character": character,
292+
"language": language,
293+
"status": "ok",
294+
"result": r,
295+
})
296+
})
271297
}
272298
LspAction::SignatureHelp => {
273299
let sig = process.signature_help(path, line, character).await;
274300
sig.map(|opt| {
275301
opt.map_or_else(
276-
|| serde_json::json!({
277-
"action": "signature_help",
278-
"path": path,
279-
"line": line,
280-
"character": character,
281-
"language": language,
282-
"status": "no_result",
283-
}),
284-
|s| serde_json::json!({
285-
"action": "signature_help",
286-
"path": path,
287-
"line": line,
288-
"character": character,
289-
"language": language,
290-
"status": "ok",
291-
"result": s,
292-
}),
302+
|| {
303+
serde_json::json!({
304+
"action": "signature_help",
305+
"path": path,
306+
"line": line,
307+
"character": character,
308+
"language": language,
309+
"status": "no_result",
310+
})
311+
},
312+
|s| {
313+
serde_json::json!({
314+
"action": "signature_help",
315+
"path": path,
316+
"line": line,
317+
"character": character,
318+
"language": language,
319+
"status": "ok",
320+
"result": s,
321+
})
322+
},
293323
)
294324
})
295325
}
296326
LspAction::CodeLens => {
297327
let lenses = process.code_lens(path).await;
298-
lenses.map(|l| serde_json::json!({
299-
"action": "code_lens",
300-
"path": path,
301-
"language": language,
302-
"status": "ok",
303-
"lenses": l,
304-
}))
328+
lenses.map(|l| {
329+
serde_json::json!({
330+
"action": "code_lens",
331+
"path": path,
332+
"language": language,
333+
"status": "ok",
334+
"lenses": l,
335+
})
336+
})
305337
}
306338
LspAction::WorkspaceSymbols => {
307339
let query = _query.unwrap_or("");
308340
let symbols = process.workspace_symbols(query).await;
309-
symbols.map(|syms| serde_json::json!({
310-
"action": "workspace_symbols",
311-
"language": language,
312-
"query": query,
313-
"status": "ok",
314-
"symbols": syms,
315-
}))
341+
symbols.map(|syms| {
342+
serde_json::json!({
343+
"action": "workspace_symbols",
344+
"language": language,
345+
"query": query,
346+
"status": "ok",
347+
"symbols": syms,
348+
})
349+
})
316350
}
317351
LspAction::Diagnostics => unreachable!(),
318352
}

rust/crates/runtime/src/lsp_client/mod.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
//! LSP (Language Server Protocol) client registry for tool dispatch.
33
44
mod dispatch;
5-
mod types;
65
#[cfg(test)]
76
mod tests;
87
#[cfg(test)]
98
mod tests_lifecycle;
9+
mod types;
1010

1111
pub use types::{
1212
LspAction, LspCodeAction, LspCodeLens, LspCommand, LspCompletionItem, LspDiagnostic,
13-
LspFileEdit, LspHoverResult, LspLocation, LspParameterInfo, LspRenameResult,
14-
LspServerState, LspServerStatus, LspSignatureHelpResult, LspSignatureInformation,
15-
LspSymbol, LspTextEdit, LspWorkspaceEdit,
13+
LspFileEdit, LspHoverResult, LspLocation, LspParameterInfo, LspRenameResult, LspServerState,
14+
LspServerStatus, LspSignatureHelpResult, LspSignatureInformation, LspSymbol, LspTextEdit,
15+
LspWorkspaceEdit,
1616
};
1717

1818
use std::collections::{HashMap, HashSet};
@@ -190,7 +190,11 @@ impl LspRegistry {
190190
/// List all registered servers.
191191
pub fn list_servers(&self) -> Vec<LspServerState> {
192192
let inner = self.inner.lock().expect("lsp registry lock poisoned");
193-
inner.servers.values().map(|entry| entry.state.clone()).collect()
193+
inner
194+
.servers
195+
.values()
196+
.map(|entry| entry.state.clone())
197+
.collect()
194198
}
195199

196200
/// Add diagnostics to a server.
@@ -274,14 +278,14 @@ impl LspRegistry {
274278
};
275279

276280
// If no descriptor, try discovery
277-
let descriptor = if let Some(d) = descriptor { d } else {
281+
let descriptor = if let Some(d) = descriptor {
282+
d
283+
} else {
278284
let available = discover_available_servers();
279285
available
280286
.into_iter()
281287
.find(|d| d.language == language)
282-
.ok_or_else(|| {
283-
format!("no LSP server descriptor found for language: {language}")
284-
})?
288+
.ok_or_else(|| format!("no LSP server descriptor found for language: {language}"))?
285289
};
286290

287291
let root_path = {
@@ -447,7 +451,6 @@ impl LspRegistry {
447451
diagnostics
448452
}
449453

450-
451454
/// Notify the LSP server that a file was closed.
452455
/// Best-effort: returns empty vec if no server is available.
453456
pub fn notify_file_close(&self, path: &str) -> Vec<LspDiagnostic> {
@@ -498,8 +501,7 @@ impl LspRegistry {
498501
let new_diags = process.drain_diagnostics();
499502
if !new_diags.is_empty() {
500503
let diag_path = path.to_owned();
501-
let mut inner =
502-
self.inner.lock().expect("lsp registry lock poisoned");
504+
let mut inner = self.inner.lock().expect("lsp registry lock poisoned");
503505
if let Some(entry) = inner.servers.get_mut(&language) {
504506
entry.state.diagnostics.retain(|d| d.path != diag_path);
505507
entry.state.diagnostics.extend(new_diags);

rust/crates/runtime/src/lsp_client/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Tests for the LSP client registry: registration, diagnostics, and type unit tests.
22
3-
use super::*;
43
use super::types::*;
4+
use super::*;
55

66
#[test]
77
fn registers_and_retrieves_server() {

0 commit comments

Comments
 (0)