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
17 changes: 17 additions & 0 deletions RFC.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,23 @@ the inner fields.
PascalCase variant names visually distinguish the type tag from the lowercase
structural fields inside (`step`, `path`, `graph`).

### File Extensions

Toolpath documents use a two-part extension encoding the document type and
serialization format:

| Extension | Document type | Description |
| --------- | ------------- | ----------- |
| `.path.json` | Path (canonical) | A complete `{"Path": {...}}` JSON document. |
| `.path.jsonl` | Path (streaming) | A line-oriented JSONL stream that seals to a `Path`. See the [JSONL Streaming RFC](docs/RFC-jsonl.md). |

`Step` and `Graph` documents use plain `.json` files with the appropriate
`{"Step": ...}` or `{"Graph": ...}` envelope. Only `Path` has a streaming
peer format.

Graph `$ref` entries MUST point to sealed `.path.json` files, not to
`.path.jsonl` streams.

### ID Uniqueness

IDs must be unique within their containing scope:
Expand Down
25 changes: 12 additions & 13 deletions crates/toolpath-claude/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,16 @@ pub fn derive_path(conversation: &Conversation, config: &DeriveConfig) -> Path {
Some(MessageContent::Parts(parts)) => {
for part in parts {
match part {
ContentPart::Text { text } => {
if !text.trim().is_empty() {
text_parts.push(text.clone());
}
ContentPart::Text { text }
if !text.trim().is_empty() =>
{
text_parts.push(text.clone());
}
ContentPart::Thinking { thinking, .. } => {
if config.include_thinking && !thinking.trim().is_empty() {
text_parts.push(format!("[thinking] {}", thinking));
}
ContentPart::Thinking { thinking, .. }
if config.include_thinking
&& !thinking.trim().is_empty() =>
{
text_parts.push(format!("[thinking] {}", thinking));
}
ContentPart::ToolUse { name, input, .. } => {
tool_uses.push(name.clone());
Expand All @@ -127,12 +128,10 @@ pub fn derive_path(conversation: &Conversation, config: &DeriveConfig) -> Path {
}
}
}
Some(MessageContent::Text(text)) => {
if !text.trim().is_empty() {
text_parts.push(text.clone());
}
Some(MessageContent::Text(text)) if !text.trim().is_empty() => {
text_parts.push(text.clone());
}
None => {}
_ => {}
}

// Skip entries with no conversation content and no file changes
Expand Down
2 changes: 1 addition & 1 deletion crates/toolpath-claude/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl ConvoIO {
}
}

metadata.sort_by(|a, b| b.last_activity.cmp(&a.last_activity));
metadata.sort_by_key(|m| std::cmp::Reverse(m.last_activity));
Ok(metadata)
}

Expand Down
4 changes: 2 additions & 2 deletions crates/toolpath-claude/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ impl ClaudeConvo {
}
}

metadata.sort_by(|a, b| b.last_activity.cmp(&a.last_activity));
metadata.sort_by_key(|m| std::cmp::Reverse(m.last_activity));
Ok(metadata)
}

Expand Down Expand Up @@ -316,7 +316,7 @@ impl ClaudeConvo {
}
}

conversations.sort_by(|a, b| b.last_activity.cmp(&a.last_activity));
conversations.sort_by_key(|c| std::cmp::Reverse(c.last_activity));
Ok(conversations)
}

Expand Down
Loading
Loading