Skip to content

Commit e07bd76

Browse files
zenshanda-ai
andcommitted
feat: per-agent model selection, shell custom name, and json_candidates export
- Sub-agents and call-agents now use configured model from models map when available, falling back to parent model - Add CompletionRunner::reserve_chat_history() builder method - Export json_candidates() as public utility for parsing model JSON output - Allow ShellTool to accept a custom name for multi-instance scenarios - Bump anda_engine to 0.11.31 Co-Authored-By: Anda Bot <noreply@anda.bot>
1 parent ac06c5b commit e07bd76

4 files changed

Lines changed: 30 additions & 8 deletions

File tree

‎anda_engine/Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "anda_engine"
33
description = "Agents engine for Anda -- an AI agent framework built with Rust, powered by ICP and TEEs."
44
repository = "https://github.com/ldclabs/anda/tree/main/anda_engine"
55
publish = true
6-
version = "0.11.30"
6+
version = "0.11.31"
77
edition.workspace = true
88
keywords.workspace = true
99
categories.workspace = true

‎anda_engine/src/context/agent.rs‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,10 @@ impl AgentCtx {
120120
.child(format!("A:{}", agent_name.to_ascii_lowercase()))?,
121121
label: agent_label.to_string(),
122122
root: self.root.clone(),
123-
model: self.model.clone(),
123+
model: self
124+
.models
125+
.get(agent_label)
126+
.unwrap_or_else(|| self.model.clone()),
124127
models: self.models.clone(),
125128
tools: self.tools.clone(),
126129
agents: self.agents.clone(),
@@ -159,7 +162,10 @@ impl AgentCtx {
159162
)?,
160163
label: agent_label.to_string(),
161164
root: self.root.clone(),
162-
model: self.model.clone(),
165+
model: self
166+
.models
167+
.get(agent_label)
168+
.unwrap_or_else(|| self.model.clone()),
163169
models: self.models.clone(),
164170
tools: self.tools.clone(),
165171
agents: self.agents.clone(),
@@ -1000,6 +1006,14 @@ impl CompletionRunner {
10001006
}
10011007
}
10021008

1009+
/// Reserves the chat history for the completion runner.
1010+
pub fn reserve_chat_history(self, chat_history: Vec<Message>) -> Self {
1011+
Self {
1012+
chat_history,
1013+
..self
1014+
}
1015+
}
1016+
10031017
/// Returns whether the completion has finished.
10041018
pub fn is_done(&self) -> bool {
10051019
self.done

‎anda_engine/src/context/tool.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ async fn select_requested_names_with_model(
405405
}
406406

407407
fn parse_selector_tool_names(content: &str) -> Vec<String> {
408-
for candidate in selector_json_candidates(content) {
408+
for candidate in json_candidates(content) {
409409
if let Ok(output) = serde_json::from_str::<ToolsSelectNamesOutput>(&candidate) {
410410
return output.tools;
411411
}
@@ -417,7 +417,8 @@ fn parse_selector_tool_names(content: &str) -> Vec<String> {
417417
Vec::new()
418418
}
419419

420-
fn selector_json_candidates(content: &str) -> Vec<String> {
420+
/// Extracts JSON candidates from the input string by applying various heuristics, such as stripping markdown code blocks and extracting JSON-like substrings. This increases the chances of successfully parsing the model output even when it is not perfectly formatted.
421+
pub fn json_candidates(content: &str) -> Vec<String> {
421422
let mut candidates = Vec::new();
422423
let mut seen = BTreeSet::new();
423424

‎anda_engine/src/extension/shell.rs‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ pub type ShellToolHook = DynToolHook<ExecArgs, ExecOutput>;
223223
pub struct ShellTool {
224224
runtime: Arc<dyn Executor>,
225225
envs: HashMap<String, String>,
226+
name: String,
226227
description: String,
227228
}
228229

@@ -235,7 +236,12 @@ impl ShellTool {
235236
/// The environment map is not forwarded wholesale. Agents must request
236237
/// specific keys through [`ExecArgs::env_keys`], and invalid environment
237238
/// variable names are ignored.
238-
pub fn new(runtime: Arc<dyn Executor>, envs: HashMap<String, String>) -> Self {
239+
pub fn new(
240+
runtime: Arc<dyn Executor>,
241+
envs: HashMap<String, String>,
242+
name: Option<String>,
243+
) -> Self {
244+
let name = name.unwrap_or_else(|| Self::NAME.to_string());
239245
let description = format!(
240246
"Execute a shell command in the workspace directory (Runtime: {}, OS: {}, Shell: {})",
241247
runtime.name(),
@@ -246,6 +252,7 @@ impl ShellTool {
246252
Self {
247253
runtime,
248254
envs,
255+
name,
249256
description,
250257
}
251258
}
@@ -291,7 +298,7 @@ impl Tool<BaseCtx> for ShellTool {
291298
type Output = ExecOutput;
292299

293300
fn name(&self) -> String {
294-
Self::NAME.to_string()
301+
self.name.clone()
295302
}
296303

297304
fn description(&self) -> String {
@@ -676,7 +683,7 @@ mod tests {
676683
let mut envs = HashMap::new();
677684
envs.insert("ANDA_TEST_ENV".to_string(), "configured".to_string());
678685
envs.insert("INVALID-NAME".to_string(), "ignored".to_string());
679-
let tool = ShellTool::new(Arc::new(TestRuntime::new("sandbox")), envs);
686+
let tool = ShellTool::new(Arc::new(TestRuntime::new("sandbox")), envs, None);
680687

681688
let collected = tool.collect_shell_env_vars(&[
682689
" ANDA_TEST_ENV ".to_string(),

0 commit comments

Comments
 (0)