Skip to content

Commit 509baee

Browse files
committed
Bump version to 0.1.0-rc.2
- Update tool implementations for Anthropic OAuth API restrictions
1 parent ec2cc50 commit 509baee

14 files changed

Lines changed: 113 additions & 71 deletions

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "codey"
3-
version = "0.1.0-rc.1"
3+
version = "0.1.0-rc.2"
44
edition = "2021"
55
authors = ["Codey Contributors"]
66
description = "A terminal-based AI coding assistant"

src/config.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ use anyhow::{Context, Result};
77
use serde::{Deserialize, Serialize};
88

99
use crate::tool_filter::ToolFilterConfig;
10+
use crate::tools::{
11+
EditFileTool, FetchUrlTool, ReadFileTool, ShellTool, WebSearchTool, WriteFileTool,
12+
};
1013

1114
/// Main configuration structure
1215
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -227,12 +230,12 @@ impl Default for ToolsConfig {
227230
fn default() -> Self {
228231
Self {
229232
enabled: vec![
230-
"read_file".to_string(),
231-
"write_file".to_string(),
232-
"edit_file".to_string(),
233-
"shell".to_string(),
234-
"fetch_url".to_string(),
235-
"web_search".to_string(),
233+
ReadFileTool::NAME.to_string(),
234+
WriteFileTool::NAME.to_string(),
235+
EditFileTool::NAME.to_string(),
236+
ShellTool::NAME.to_string(),
237+
FetchUrlTool::NAME.to_string(),
238+
WebSearchTool::NAME.to_string(),
236239
],
237240
shell: ToolFilterConfig::default(),
238241
read_file: ToolFilterConfig::default(),
@@ -248,12 +251,12 @@ impl ToolsConfig {
248251
/// Build a HashMap of tool filters for compilation
249252
pub fn filters(&self) -> HashMap<String, ToolFilterConfig> {
250253
let mut map = HashMap::new();
251-
map.insert("shell".to_string(), self.shell.clone());
252-
map.insert("read_file".to_string(), self.read_file.clone());
253-
map.insert("write_file".to_string(), self.write_file.clone());
254-
map.insert("edit_file".to_string(), self.edit_file.clone());
255-
map.insert("fetch_url".to_string(), self.fetch_url.clone());
256-
map.insert("web_search".to_string(), self.web_search.clone());
254+
map.insert(ShellTool::NAME.to_string(), self.shell.clone());
255+
map.insert(ReadFileTool::NAME.to_string(), self.read_file.clone());
256+
map.insert(WriteFileTool::NAME.to_string(), self.write_file.clone());
257+
map.insert(EditFileTool::NAME.to_string(), self.edit_file.clone());
258+
map.insert(FetchUrlTool::NAME.to_string(), self.fetch_url.clone());
259+
map.insert(WebSearchTool::NAME.to_string(), self.web_search.clone());
257260
map
258261
}
259262
}
@@ -331,7 +334,7 @@ mod tests {
331334
fn test_default_config() {
332335
let config = Config::default();
333336
assert_eq!(config.agents.foreground.model, "claude-opus-4-5-20251101");
334-
assert!(config.tools.enabled.contains(&"read_file".to_string()));
337+
assert!(config.tools.enabled.contains(&ReadFileTool::NAME.to_string()));
335338
}
336339

337340
#[test]

src/llm/agent.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ use crate::tools::{ToolCall, ToolDecision, ToolRegistry};
1818
const ANTHROPIC_BETA_HEADER: &str = concat!(
1919
"oauth-2025-04-20,",
2020
"claude-code-20250219,",
21-
"interleaved-thinking-2025-05-14,",
22-
"fine-grained-tool-streaming-2025-05-14",
21+
"interleaved-thinking-2025-05-14",
22+
// Removed: causes OAuth rejection before tool calls are processed
23+
// "fine-grained-tool-streaming-2025-05-14",
2324
);
24-
const ANTHROPIC_USER_AGENT: &str =
25-
"ai-sdk/anthropic/2.0.50 ai-sdk/provider-utils/3.0.18 runtime/bun/1.3.4";
25+
const ANTHROPIC_USER_AGENT: &str = "claude-cli/2.1.2 (external, cli)";
2626

2727
// Only expose internal ToolCall
2828
// Note: agent_id is set to 0 here - the caller (App) should set the correct ID

src/tool_filter.rs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ use fancy_regex::Regex;
3535
use serde::{Deserialize, Serialize};
3636

3737
use crate::tools::ToolDecision;
38+
use crate::tools::{
39+
EditFileTool, FetchUrlTool, ReadFileTool, ShellTool, WebSearchTool, WriteFileTool,
40+
};
3841

3942
/// Filter configuration with allow and deny pattern lists
4043
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
@@ -94,12 +97,12 @@ impl CompiledToolFilter {
9497
/// Get the primary parameter name for a tool
9598
fn primary_param(tool_name: &str) -> &'static str {
9699
match tool_name {
97-
"shell" => "command",
98-
"read_file" => "path",
99-
"write_file" => "path",
100-
"edit_file" => "path",
101-
"fetch_url" => "url",
102-
"web_search" => "query",
100+
x if x == ShellTool::NAME => "command",
101+
x if x == ReadFileTool::NAME => "path",
102+
x if x == WriteFileTool::NAME => "path",
103+
x if x == EditFileTool::NAME => "path",
104+
x if x == FetchUrlTool::NAME => "url",
105+
x if x == WebSearchTool::NAME => "query",
103106
_ => "command", // Default fallback
104107
}
105108
}
@@ -158,7 +161,7 @@ mod tests {
158161
allow: vec![r"^ls\b".to_string(), r"^cat\b".to_string()],
159162
deny: vec![],
160163
};
161-
let filter = CompiledToolFilter::compile("shell", &config).unwrap();
164+
let filter = CompiledToolFilter::compile(ShellTool::NAME, &config).unwrap();
162165

163166
assert_eq!(filter.evaluate("ls -la"), Some(ToolDecision::Approve));
164167
assert_eq!(filter.evaluate("cat file.txt"), Some(ToolDecision::Approve));
@@ -171,7 +174,7 @@ mod tests {
171174
allow: vec![],
172175
deny: vec![r"rm\s+-rf\s+/".to_string(), r"sudo\s+rm".to_string()],
173176
};
174-
let filter = CompiledToolFilter::compile("shell", &config).unwrap();
177+
let filter = CompiledToolFilter::compile(ShellTool::NAME, &config).unwrap();
175178

176179
assert_eq!(filter.evaluate("rm -rf /"), Some(ToolDecision::Deny));
177180
assert_eq!(filter.evaluate("sudo rm -rf"), Some(ToolDecision::Deny));
@@ -184,7 +187,7 @@ mod tests {
184187
allow: vec![r"^ls".to_string()],
185188
deny: vec![r"sudo".to_string()],
186189
};
187-
let filter = CompiledToolFilter::compile("shell", &config).unwrap();
190+
let filter = CompiledToolFilter::compile(ShellTool::NAME, &config).unwrap();
188191

189192
// "sudo ls" matches both allow (^ls) and deny (sudo), deny wins
190193
assert_eq!(filter.evaluate("sudo ls"), Some(ToolDecision::Deny));
@@ -199,19 +202,19 @@ mod tests {
199202
};
200203

201204
let mut configs = HashMap::new();
202-
configs.insert("shell".to_string(), config);
205+
configs.insert(ShellTool::NAME.to_string(), config);
203206
let filters = ToolFilters::compile(&configs).unwrap();
204207

205208
assert_eq!(
206-
filters.evaluate("shell", &json!({"command": "ls -la"})),
209+
filters.evaluate(ShellTool::NAME, &json!({"command": "ls -la"})),
207210
Some(ToolDecision::Approve)
208211
);
209212
assert_eq!(
210-
filters.evaluate("shell", &json!({"command": "rm -rf /"})),
213+
filters.evaluate(ShellTool::NAME, &json!({"command": "rm -rf /"})),
211214
Some(ToolDecision::Deny)
212215
);
213216
assert_eq!(
214-
filters.evaluate("shell", &json!({"command": "echo hello"})),
217+
filters.evaluate(ShellTool::NAME, &json!({"command": "echo hello"})),
215218
None
216219
);
217220
}
@@ -224,19 +227,19 @@ mod tests {
224227
};
225228

226229
let mut configs = HashMap::new();
227-
configs.insert("read_file".to_string(), config);
230+
configs.insert(ReadFileTool::NAME.to_string(), config);
228231
let filters = ToolFilters::compile(&configs).unwrap();
229232

230233
assert_eq!(
231-
filters.evaluate("read_file", &json!({"path": "src/main.rs"})),
234+
filters.evaluate(ReadFileTool::NAME, &json!({"path": "src/main.rs"})),
232235
Some(ToolDecision::Approve)
233236
);
234237
assert_eq!(
235-
filters.evaluate("read_file", &json!({"path": ".env"})),
238+
filters.evaluate(ReadFileTool::NAME, &json!({"path": ".env"})),
236239
Some(ToolDecision::Deny)
237240
);
238241
assert_eq!(
239-
filters.evaluate("read_file", &json!({"path": "README.md"})),
242+
filters.evaluate(ReadFileTool::NAME, &json!({"path": "README.md"})),
240243
None
241244
);
242245
}
@@ -249,12 +252,12 @@ mod tests {
249252
};
250253

251254
let mut configs = HashMap::new();
252-
configs.insert("shell".to_string(), config);
255+
configs.insert(ShellTool::NAME.to_string(), config);
253256
let filters = ToolFilters::compile(&configs).unwrap();
254257

255258
// Missing "command" param should result in None
256259
assert_eq!(
257-
filters.evaluate("shell", &json!({"other_param": "value"})),
260+
filters.evaluate(ShellTool::NAME, &json!({"other_param": "value"})),
258261
None
259262
);
260263
}
@@ -265,7 +268,7 @@ mod tests {
265268
allow: vec![r"[invalid".to_string()],
266269
deny: vec![],
267270
};
268-
let result = CompiledToolFilter::compile("shell", &config);
271+
let result = CompiledToolFilter::compile(ShellTool::NAME, &config);
269272
assert!(result.is_err());
270273
}
271274

@@ -277,7 +280,7 @@ mod tests {
277280
};
278281

279282
let mut configs = HashMap::new();
280-
configs.insert("shell".to_string(), config);
283+
configs.insert(ShellTool::NAME.to_string(), config);
281284
let filters = ToolFilters::compile(&configs).unwrap();
282285

283286
// Unknown tool returns None
@@ -290,12 +293,12 @@ mod tests {
290293
#[test]
291294
fn test_empty_config_skipped() {
292295
let mut configs = HashMap::new();
293-
configs.insert("shell".to_string(), ToolFilterConfig::default());
296+
configs.insert(ShellTool::NAME.to_string(), ToolFilterConfig::default());
294297
let filters = ToolFilters::compile(&configs).unwrap();
295298

296299
// Empty config means no filter registered
297300
assert_eq!(
298-
filters.evaluate("shell", &json!({"command": "ls"})),
301+
filters.evaluate(ShellTool::NAME, &json!({"command": "ls"})),
299302
None
300303
);
301304
}

src/tools/impls/edit_file.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,13 @@ struct SearchReplace {
185185
new_string: String,
186186
}
187187

188+
impl EditFileTool {
189+
pub const NAME: &'static str = "mcp_edit_file";
190+
}
191+
188192
impl Tool for EditFileTool {
189193
fn name(&self) -> &'static str {
190-
"edit_file"
194+
Self::NAME
191195
}
192196

193197
fn description(&self) -> &'static str {
@@ -324,7 +328,7 @@ mod tests {
324328
executor.enqueue(vec![ToolCall {
325329
agent_id: 0,
326330
call_id: "test".to_string(),
327-
name: "edit_file".to_string(),
331+
name: EditFileTool::NAME.to_string(),
328332
params: json!({
329333
"path": file_path.to_str().unwrap(),
330334
"edits": [{
@@ -357,7 +361,7 @@ mod tests {
357361
executor.enqueue(vec![ToolCall {
358362
agent_id: 0,
359363
call_id: "test".to_string(),
360-
name: "edit_file".to_string(),
364+
name: EditFileTool::NAME.to_string(),
361365
params: json!({
362366
"path": file_path.to_str().unwrap(),
363367
"edits": [
@@ -387,7 +391,7 @@ mod tests {
387391
executor.enqueue(vec![ToolCall {
388392
agent_id: 0,
389393
call_id: "test".to_string(),
390-
name: "edit_file".to_string(),
394+
name: EditFileTool::NAME.to_string(),
391395
params: json!({
392396
"path": "/nonexistent/file.rs",
393397
"edits": [{ "old_string": "foo", "new_string": "bar" }]
@@ -416,7 +420,7 @@ mod tests {
416420
executor.enqueue(vec![ToolCall {
417421
agent_id: 0,
418422
call_id: "test".to_string(),
419-
name: "edit_file".to_string(),
423+
name: EditFileTool::NAME.to_string(),
420424
params: json!({
421425
"path": file_path.to_str().unwrap(),
422426
"edits": [{ "old_string": "foo", "new_string": "bar" }]
@@ -445,7 +449,7 @@ mod tests {
445449
executor.enqueue(vec![ToolCall {
446450
agent_id: 0,
447451
call_id: "test".to_string(),
448-
name: "edit_file".to_string(),
452+
name: EditFileTool::NAME.to_string(),
449453
params: json!({
450454
"path": file_path.to_str().unwrap(),
451455
"edits": [{ "old_string": "goodbye", "new_string": "farewell" }]

src/tools/impls/fetch_html.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,13 @@ struct FetchHtmlParams {
104104
max_length: Option<usize>,
105105
}
106106

107+
impl FetchHtmlTool {
108+
pub const NAME: &'static str = "mcp_fetch_html";
109+
}
110+
107111
impl Tool for FetchHtmlTool {
108112
fn name(&self) -> &'static str {
109-
"fetch_html"
113+
Self::NAME
110114
}
111115

112116
fn description(&self) -> &'static str {
@@ -169,7 +173,7 @@ mod tests {
169173
executor.enqueue(vec![ToolCall {
170174
agent_id: 0,
171175
call_id: "test".to_string(),
172-
name: "fetch_html".to_string(),
176+
name: FetchHtmlTool::NAME.to_string(),
173177
params: json!({ "url": "not a valid url" }),
174178
decision: ToolDecision::Approve,
175179
}]);
@@ -190,7 +194,7 @@ mod tests {
190194
executor.enqueue(vec![ToolCall {
191195
agent_id: 0,
192196
call_id: "test".to_string(),
193-
name: "fetch_html".to_string(),
197+
name: FetchHtmlTool::NAME.to_string(),
194198
params: json!({ "url": "ftp://example.com/file" }),
195199
decision: ToolDecision::Approve,
196200
}]);

src/tools/impls/fetch_url.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,13 @@ struct FetchUrlParams {
9595
max_length: Option<usize>,
9696
}
9797

98+
impl FetchUrlTool {
99+
pub const NAME: &'static str = "mcp_fetch_url";
100+
}
101+
98102
impl Tool for FetchUrlTool {
99103
fn name(&self) -> &'static str {
100-
"fetch_url"
104+
Self::NAME
101105
}
102106

103107
fn description(&self) -> &'static str {
@@ -160,7 +164,7 @@ mod tests {
160164
executor.enqueue(vec![ToolCall {
161165
agent_id: 0,
162166
call_id: "test".to_string(),
163-
name: "fetch_url".to_string(),
167+
name: FetchUrlTool::NAME.to_string(),
164168
params: json!({ "url": "not a valid url" }),
165169
decision: ToolDecision::Approve,
166170
}]);
@@ -181,7 +185,7 @@ mod tests {
181185
executor.enqueue(vec![ToolCall {
182186
agent_id: 0,
183187
call_id: "test".to_string(),
184-
name: "fetch_url".to_string(),
188+
name: FetchUrlTool::NAME.to_string(),
185189
params: json!({ "url": "ftp://example.com/file" }),
186190
decision: ToolDecision::Approve,
187191
}]);

src/tools/impls/open_file.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ struct OpenFileParams {
1919
line: Option<u32>,
2020
}
2121

22+
impl OpenFileTool {
23+
pub const NAME: &'static str = "mcp_open_file";
24+
}
25+
2226
impl Tool for OpenFileTool {
2327
fn name(&self) -> &'static str {
24-
"open_file"
28+
Self::NAME
2529
}
2630

2731
fn description(&self) -> &'static str {

0 commit comments

Comments
 (0)