Skip to content

Commit fbf08eb

Browse files
committed
Add integ tests, update agent protocol
1 parent 56ea77e commit fbf08eb

File tree

29 files changed

+1917
-660
lines changed

29 files changed

+1917
-660
lines changed

Cargo.lock

Lines changed: 25 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,3 @@ opt-level = 3
216216

217217
[profile.dev.package.similar]
218218
opt-level = 3
219-
220-
[profile.dev.package.backtrace]
221-
opt-level = 3

crates/agent/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ rustls-native-certs.workspace = true
5858
schemars = "1.0.4"
5959
semver.workspace = true
6060
serde.workspace = true
61+
serde_bytes = "0.11.19"
6162
serde_json.workspace = true
6263
sha2.workspace = true
6364
shellexpand.workspace = true

crates/agent/src/agent/agent_config/definitions.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,78 +14,77 @@ use crate::agent::consts::DEFAULT_AGENT_NAME;
1414
use crate::agent::tools::BuiltInToolName;
1515

1616
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
17-
// #[serde(tag = "specVersion")]
1817
#[serde(untagged)]
19-
pub enum Config {
18+
pub enum AgentConfig {
2019
#[serde(rename = "2025_08_22")]
2120
V2025_08_22(AgentConfigV2025_08_22),
2221
}
2322

24-
impl Default for Config {
23+
impl Default for AgentConfig {
2524
fn default() -> Self {
2625
Self::V2025_08_22(AgentConfigV2025_08_22::default())
2726
}
2827
}
2928

30-
impl Config {
29+
impl AgentConfig {
3130
pub fn name(&self) -> &str {
3231
match self {
33-
Config::V2025_08_22(a) => a.name.as_str(),
32+
AgentConfig::V2025_08_22(a) => a.name.as_str(),
3433
}
3534
}
3635

3736
pub fn system_prompt(&self) -> Option<&str> {
3837
match self {
39-
Config::V2025_08_22(a) => a.system_prompt.as_deref(),
38+
AgentConfig::V2025_08_22(a) => a.system_prompt.as_deref(),
4039
}
4140
}
4241

4342
pub fn tools(&self) -> Vec<String> {
4443
match self {
45-
Config::V2025_08_22(a) => a.tools.clone(),
44+
AgentConfig::V2025_08_22(a) => a.tools.clone(),
4645
}
4746
}
4847

4948
pub fn tool_aliases(&self) -> &HashMap<String, String> {
5049
match self {
51-
Config::V2025_08_22(a) => &a.tool_aliases,
50+
AgentConfig::V2025_08_22(a) => &a.tool_aliases,
5251
}
5352
}
5453

5554
pub fn tool_settings(&self) -> Option<&ToolSettings> {
5655
match self {
57-
Config::V2025_08_22(a) => a.tool_settings.as_ref(),
56+
AgentConfig::V2025_08_22(a) => a.tool_settings.as_ref(),
5857
}
5958
}
6059

6160
pub fn allowed_tools(&self) -> &HashSet<String> {
6261
match self {
63-
Config::V2025_08_22(a) => &a.allowed_tools,
62+
AgentConfig::V2025_08_22(a) => &a.allowed_tools,
6463
}
6564
}
6665

6766
pub fn hooks(&self) -> &HashMap<HookTrigger, Vec<HookConfig>> {
6867
match self {
69-
Config::V2025_08_22(a) => &a.hooks,
68+
AgentConfig::V2025_08_22(a) => &a.hooks,
7069
}
7170
}
7271

7372
// pub fn resources(&self) -> &[impl AsRef<str>] {
7473
pub fn resources(&self) -> &[impl AsRef<str>] {
7574
match self {
76-
Config::V2025_08_22(a) => a.resources.as_slice(),
75+
AgentConfig::V2025_08_22(a) => a.resources.as_slice(),
7776
}
7877
}
7978

8079
pub fn mcp_servers(&self) -> &HashMap<String, McpServerConfig> {
8180
match self {
82-
Config::V2025_08_22(a) => &a.mcp_servers,
81+
AgentConfig::V2025_08_22(a) => &a.mcp_servers,
8382
}
8483
}
8584

8685
pub fn use_legacy_mcp_json(&self) -> bool {
8786
match self {
88-
Config::V2025_08_22(a) => a.use_legacy_mcp_json,
87+
AgentConfig::V2025_08_22(a) => a.use_legacy_mcp_json,
8988
}
9089
}
9190
}
@@ -112,7 +111,6 @@ pub struct AgentConfigV2025_08_22 {
112111
///
113112
/// fs_read
114113
/// fs_write
115-
/// directory
116114
/// @mcp_server_name/tool_name
117115
/// #agent_name
118116
#[serde(default)]
@@ -193,18 +191,18 @@ impl Default for AgentConfigV2025_08_22 {
193191

194192
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
195193
pub struct ToolSettings {
196-
pub file_read: FileReadSettings,
197-
pub file_write: FileWriteSettings,
194+
pub fs_read: FsReadSettings,
195+
pub fs_write: FsWriteSettings,
198196
}
199197

200198
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
201-
pub struct FileReadSettings {
199+
pub struct FsReadSettings {
202200
pub allowed_paths: Vec<String>,
203201
pub denied_paths: Vec<String>,
204202
}
205203

206204
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
207-
pub struct FileWriteSettings {
205+
pub struct FsWriteSettings {
208206
pub allowed_paths: Vec<String>,
209207
pub denied_paths: Vec<String>,
210208
}
@@ -392,6 +390,6 @@ mod tests {
392390
"description": "The orchestrator agent",
393391
});
394392

395-
let _: Config = serde_json::from_value(agent).unwrap();
393+
let _: AgentConfig = serde_json::from_value(agent).unwrap();
396394
}
397395
}

crates/agent/src/agent/agent_config/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::path::{
1212
};
1313

1414
use definitions::{
15-
Config,
15+
AgentConfig,
1616
HookConfig,
1717
HookTrigger,
1818
McpServerConfig,
@@ -53,11 +53,11 @@ pub struct LoadedAgentConfig {
5353
#[allow(dead_code)]
5454
source: ConfigSource,
5555
/// The actual config content
56-
config: Config,
56+
config: AgentConfig,
5757
}
5858

5959
impl LoadedAgentConfig {
60-
pub fn config(&self) -> &Config {
60+
pub fn config(&self) -> &AgentConfig {
6161
&self.config
6262
}
6363

@@ -190,18 +190,18 @@ pub async fn load_agents() -> Result<(Vec<LoadedAgentConfig>, Vec<AgentConfigErr
190190
Ok((agent_configs, invalid_agents))
191191
}
192192

193-
pub async fn load_workspace_agents() -> Result<(Vec<(PathBuf, Config)>, Vec<AgentConfigError>)> {
193+
pub async fn load_workspace_agents() -> Result<(Vec<(PathBuf, AgentConfig)>, Vec<AgentConfigError>)> {
194194
load_agents_from_dir(local_agents_path()?, true).await
195195
}
196196

197-
pub async fn load_global_agents() -> Result<(Vec<(PathBuf, Config)>, Vec<AgentConfigError>)> {
197+
pub async fn load_global_agents() -> Result<(Vec<(PathBuf, AgentConfig)>, Vec<AgentConfigError>)> {
198198
load_agents_from_dir(global_agents_path()?, true).await
199199
}
200200

201201
async fn load_agents_from_dir(
202202
dir: impl AsRef<Path>,
203203
create_if_missing: bool,
204-
) -> Result<(Vec<(PathBuf, Config)>, Vec<AgentConfigError>)> {
204+
) -> Result<(Vec<(PathBuf, AgentConfig)>, Vec<AgentConfigError>)> {
205205
let dir = dir.as_ref();
206206

207207
if !dir.exists() && create_if_missing {
@@ -214,7 +214,7 @@ async fn load_agents_from_dir(
214214
.await
215215
.with_context(|| format!("failed to read local agents directory {:?}", &dir))?;
216216

217-
let mut agents: Vec<(PathBuf, Config)> = vec![];
217+
let mut agents: Vec<(PathBuf, AgentConfig)> = vec![];
218218
let mut invalid_agents: Vec<AgentConfigError> = vec![];
219219

220220
loop {
@@ -294,7 +294,7 @@ pub struct LoadedMcpServerConfigs {
294294
impl LoadedMcpServerConfigs {
295295
/// Loads MCP configs from the given agent config, taking into consideration global and
296296
/// workspace MCP config files for when the use_legacy_mcp_json field is true.
297-
pub async fn from_agent_config(config: &Config) -> LoadedMcpServerConfigs {
297+
pub async fn from_agent_config(config: &AgentConfig) -> LoadedMcpServerConfigs {
298298
let mut configs = vec![];
299299
let mut overwritten_configs = vec![];
300300

crates/agent/src/agent/agent_config/parse.rs

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
use std::borrow::Cow;
44
use std::str::FromStr;
55

6-
use crate::agent::agent_loop::types::ToolUseBlock;
7-
use crate::agent::protocol::AgentError;
86
use crate::agent::tools::BuiltInToolName;
97
use crate::agent::util::path::canonicalize_path_sys;
108
use crate::agent::util::providers::{
@@ -125,51 +123,6 @@ impl<'a> ToolNameKind<'a> {
125123
}
126124
}
127125

128-
#[derive(Debug, Clone, thiserror::Error)]
129-
#[error("Failed to parse the tool use: {}", .kind)]
130-
pub struct ToolParseError {
131-
pub tool_use: ToolUseBlock,
132-
#[source]
133-
pub kind: ToolParseErrorKind,
134-
}
135-
136-
impl ToolParseError {
137-
pub fn new(tool_use: ToolUseBlock, kind: ToolParseErrorKind) -> Self {
138-
Self { tool_use, kind }
139-
}
140-
}
141-
142-
/// Errors associated with parsing a tool use as requested by the model into a tool ready to be
143-
/// executed.
144-
///
145-
/// Captures any errors that can occur right up to tool execution.
146-
///
147-
/// Tool parsing failures can occur in different stages:
148-
/// - Mapping the tool name to an actual tool JSON schema
149-
/// - Parsing the tool input arguments according to the tool's JSON schema
150-
/// - Tool-specific semantic validation of the input arguments
151-
#[derive(Debug, Clone, thiserror::Error)]
152-
pub enum ToolParseErrorKind {
153-
#[error("A tool with the name '{}' does not exist", .0)]
154-
NameDoesNotExist(String),
155-
#[error("The tool input does not match the tool schema: {}", .0)]
156-
SchemaFailure(String),
157-
#[error("The tool arguments failed validation: {}", .0)]
158-
InvalidArgs(String),
159-
#[error("An unexpected error occurred parsing the tools: {}", .0)]
160-
Other(#[from] AgentError),
161-
}
162-
163-
impl ToolParseErrorKind {
164-
pub fn schema_failure<T: std::error::Error>(error: T) -> Self {
165-
Self::SchemaFailure(error.to_string())
166-
}
167-
168-
pub fn invalid_args(error_message: String) -> Self {
169-
Self::InvalidArgs(error_message)
170-
}
171-
}
172-
173126
/// Represents the authoritative source of a single tool name - essentially, tool names before
174127
/// undergoing any transformations.
175128
///

0 commit comments

Comments
 (0)