Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

All notable changes to the Toolpath workspace are documented here.

## 0.2.0 — toolpath-convo / 0.3.0 — toolpath-claude

### toolpath-convo 0.2.0

- Added `WatcherEvent::TurnUpdated` variant for signaling when a previously-emitted turn has been updated with additional data (e.g. tool results that arrived in a later log entry)

### toolpath-claude 0.3.0

- **Breaking (behavioral):** `conversation_to_view()` and `ConversationProvider::load_conversation()` now perform cross-entry tool result assembly — tool-result-only user entries are absorbed into the preceding assistant turn's `ToolInvocation.result` fields instead of being emitted as separate phantom empty turns
- **Breaking (behavioral):** `ConversationWatcher` trait impl now emits `WatcherEvent::TurnUpdated` when tool results arrive, instead of emitting phantom empty user turns
- Added `Message::tool_results()` convenience method and `ToolResultRef` type, symmetric with `tool_uses()`/`ToolUseRef`
- Added shared `merge_tool_results()` that pairs results to invocations by `tool_use_id`
- Thanks to the crabcity maintainers for the detailed design request

## 0.2.1 — toolpath-claude

### toolpath-claude 0.2.1
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ license = "Apache-2.0"

[workspace.dependencies]
toolpath = { version = "0.1.5", path = "crates/toolpath" }
toolpath-convo = { version = "0.1.0", path = "crates/toolpath-convo" }
toolpath-convo = { version = "0.2.0", path = "crates/toolpath-convo" }
toolpath-git = { version = "0.1.3", path = "crates/toolpath-git" }
toolpath-claude = { version = "0.2.1", path = "crates/toolpath-claude", default-features = false }
toolpath-claude = { version = "0.3.0", path = "crates/toolpath-claude", default-features = false }
toolpath-dot = { version = "0.1.2", path = "crates/toolpath-dot" }

serde = { version = "1.0", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/toolpath-claude/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "toolpath-claude"
version = "0.2.1"
version = "0.3.0"
edition.workspace = true
license.workspace = true
repository = "https://github.com/empathic/toolpath"
Expand Down
27 changes: 26 additions & 1 deletion crates/toolpath-claude/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,12 @@ while let Some(entries) = handle.recv().await {
## Provider-agnostic usage

This crate implements `toolpath_convo::ConversationProvider`, so consumers can
code against the provider-agnostic types instead of Claude-specific structures:
code against the provider-agnostic types instead of Claude-specific structures.

Tool results are automatically assembled across entry boundaries — Claude's JSONL
writes tool invocations and their results as separate entries, but
`load_conversation` pairs them by `tool_use_id` so `ToolInvocation.result` is
populated and tool-result-only user entries are absorbed (no phantom empty turns):

```rust,ignore
use toolpath_claude::ClaudeConvo;
Expand All @@ -116,6 +121,26 @@ let view = provider.load_conversation("/path/to/project", "session-id")?;

for turn in &view.turns {
println!("[{}] {}: {}", turn.timestamp, turn.role, turn.text);
for tool_use in &turn.tool_uses {
if let Some(result) = &tool_use.result {
println!(" {} -> {}", tool_use.name, if result.is_error { "error" } else { "ok" });
}
}
}
```

The `ConversationWatcher` trait impl emits `WatcherEvent::Turn` eagerly and
follows up with `WatcherEvent::TurnUpdated` when tool results arrive:

```rust,ignore
use toolpath_convo::{ConversationWatcher, WatcherEvent};

for event in watcher.poll()? {
match event {
WatcherEvent::Turn(turn) => ui.add_turn(*turn),
WatcherEvent::TurnUpdated(turn) => ui.replace_turn(*turn),
WatcherEvent::Progress { .. } => {}
}
}
```

Expand Down
3 changes: 2 additions & 1 deletion crates/toolpath-claude/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ pub use query::{ConversationQuery, HistoryQuery};
pub use reader::ConversationReader;
pub use types::{
CacheCreation, ContentPart, Conversation, ConversationEntry, ConversationMetadata,
HistoryEntry, Message, MessageContent, MessageRole, ToolResultContent, ToolUseRef, Usage,
HistoryEntry, Message, MessageContent, MessageRole, ToolResultContent, ToolResultRef,
ToolUseRef, Usage,
};
#[cfg(feature = "watcher")]
pub use watcher::ConversationWatcher;
Expand Down
Loading