diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aa860b..c64523a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to the Toolpath workspace are documented here. +## Derive: recognize camelCase file-path tool fields — 2026-07-09 + +- **`toolpath-convo`** (0.11.3): the shared `derive_path` file-path + extractor now probes the camelCase siblings `filePath` and `fileName` + in addition to `file_path`/`filename`/`path`/`file`. Providers that + leave file-mutation synthesis to the shared derive (rather than + pre-building `Turn.file_mutations`) previously dropped a `FileWrite` + tool's artifact when its input used the camelCase convention (e.g. + opencode's `filePath`). snake_case is probed first, so existing inputs + resolve unchanged. Additive; no effect on already-derived documents. + Follow-up to the change-key relativization work (0.11.2). + ## Derive: relativize file change keys against `path.base` — 2026-07-08 - **`toolpath-convo`** (0.11.2): `derive_path` now stores file-change diff --git a/Cargo.lock b/Cargo.lock index cfb3faf..f176c72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3924,7 +3924,7 @@ dependencies = [ [[package]] name = "toolpath-convo" -version = "0.11.2" +version = "0.11.3" dependencies = [ "chrono", "jsonschema", diff --git a/Cargo.toml b/Cargo.toml index f0dfbde..1823903 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ license = "Apache-2.0" [workspace.dependencies] toolpath = { version = "0.7.0", path = "crates/toolpath" } -toolpath-convo = { version = "0.11.2", path = "crates/toolpath-convo" } +toolpath-convo = { version = "0.11.3", path = "crates/toolpath-convo" } toolpath-git = { version = "0.6.0", path = "crates/toolpath-git" } toolpath-claude = { version = "0.12.0", path = "crates/toolpath-claude", default-features = false } toolpath-gemini = { version = "0.6.0", path = "crates/toolpath-gemini", default-features = false } diff --git a/crates/toolpath-convo/Cargo.toml b/crates/toolpath-convo/Cargo.toml index e78e99e..c788053 100644 --- a/crates/toolpath-convo/Cargo.toml +++ b/crates/toolpath-convo/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "toolpath-convo" -version = "0.11.2" +version = "0.11.3" edition.workspace = true license.workspace = true repository = "https://github.com/empathic/toolpath" diff --git a/crates/toolpath-convo/src/derive.rs b/crates/toolpath-convo/src/derive.rs index 134f0e8..9ed133f 100644 --- a/crates/toolpath-convo/src/derive.rs +++ b/crates/toolpath-convo/src/derive.rs @@ -591,7 +591,9 @@ pub(crate) fn relativize_key(path: &str, base_uri: Option<&str>) -> String { } fn extract_file_path(tool: &ToolInvocation) -> Option { - for field in &["file_path", "path", "filename", "file"] { + // snake_case first so existing inputs resolve unchanged; camelCase + // siblings (`filePath`, `fileName`) cover conventions like opencode's. + for field in &["file_path", "filePath", "path", "filename", "fileName", "file"] { if let Some(v) = tool.input.get(*field) && let Some(s) = v.as_str() { @@ -1251,6 +1253,27 @@ mod tests { assert!(path.steps[0].change.contains_key("c.rs")); } + #[test] + fn test_tool_use_filewrite_with_camelcase_file_path_field() { + // camelCase `filePath` is opencode's tool-input convention; a + // provider that leaves file-mutation synthesis to the shared + // derive would otherwise drop the artifact entirely. + let mut turn = base_turn("t1", Role::Assistant); + turn.tool_uses = vec![fw_tool("write", "tu1", serde_json::json!({"filePath": "d.rs"}))]; + let view = view_with(vec![turn]); + let path = derive_path(&view, &DeriveConfig::default()); + assert!(path.steps[0].change.contains_key("d.rs")); + } + + #[test] + fn test_tool_use_filewrite_with_camelcase_file_name_field() { + let mut turn = base_turn("t1", Role::Assistant); + turn.tool_uses = vec![fw_tool("W", "tu1", serde_json::json!({"fileName": "e.rs"}))]; + let view = view_with(vec![turn]); + let path = derive_path(&view, &DeriveConfig::default()); + assert!(path.steps[0].change.contains_key("e.rs")); + } + #[test] fn test_tool_use_filewrite_no_recognized_field() { let mut turn = base_turn("t1", Role::Assistant); diff --git a/site/_data/crates.json b/site/_data/crates.json index 4e0ca01..37899b3 100644 --- a/site/_data/crates.json +++ b/site/_data/crates.json @@ -9,7 +9,7 @@ }, { "name": "toolpath-convo", - "version": "0.11.2", + "version": "0.11.3", "description": "Provider-agnostic conversation types, traits, and Toolpath-Path derivation", "docs": "https://docs.rs/toolpath-convo", "crate": "https://crates.io/crates/toolpath-convo",