Skip to content
Open
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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

All notable changes to the Toolpath workspace are documented here.

## 0.2.0 — toolpath + 0.4.0 — toolpath-cli

### toolpath 0.2.0

- Add JSONL streaming format for `Path` documents (new `v1::jsonl` module) per [docs/RFC-jsonl.md](docs/RFC-jsonl.md). Read with `Path::from_jsonl_reader` / `Path::from_jsonl_str`, write with `Path::to_jsonl_writer` / `Path::to_jsonl_string`. Line kinds: `PathOpen`, `Step`, `ActorDef`, `Signature`, `PathMeta`, `Head`, `PathClose`.
- Add `PathIdentity.graph_ref: Option<String>` — an optional `$ref`-style URL naming the graph a path belongs to. Additive and backwards-compatible; serialization omits the field when `None`, so existing documents and signatures remain byte-stable.

### toolpath-cli 0.4.0

- Accept `.path.jsonl` files wherever `--input` takes a canonical JSON path: `validate`, `render dot`, `render md`, `query *`, and `merge`. Extension-based routing via a new `io::read_document_auto` helper; stdin paths remain JSON-only in this release.
- Refactor `track` to persist sessions as `.path.jsonl` streams. The session file is still a single file per session, now in JSONL format, with tracking bookkeeping stored in `path.meta.extra["track"]` (stripped on export/close). Strict append-only writes are a future optimization.
- Rename example path documents to the two-part extension: `examples/path-*.json` → `examples/path-*.path.json`, with new `examples/path-*.path.jsonl` siblings.

## [Unreleased]

### Changed
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.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ edition = "2024"
license = "Apache-2.0"

[workspace.dependencies]
toolpath = { version = "0.1.5", path = "crates/toolpath" }
toolpath = { version = "0.2.0", path = "crates/toolpath" }
toolpath-convo = { version = "0.7.0", path = "crates/toolpath-convo" }
toolpath-git = { version = "0.1.3", path = "crates/toolpath-git" }
toolpath-claude = { version = "0.7.0", path = "crates/toolpath-claude", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions crates/toolpath-claude/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ pub fn derive_path(conversation: &Conversation, config: &DeriveConfig) -> Path {
id: format!("path-claude-{}", session_short),
base: base_uri.map(|uri| Base { uri, ref_str: None }),
head,
graph_ref: None,
},
steps,
meta: Some(PathMeta {
Expand Down
2 changes: 1 addition & 1 deletion crates/toolpath-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "toolpath-cli"
version = "0.3.1"
version = "0.4.0"
edition.workspace = true
license.workspace = true
repository = "https://github.com/empathic/toolpath"
Expand Down
27 changes: 27 additions & 0 deletions crates/toolpath-cli/examples/convert-path-to-jsonl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//! One-off helper: read a `.path.json` file, write the JSONL form to a
//! `.path.jsonl` file at the same basename. Used to regenerate the JSONL
//! example files under `examples/` whenever their JSON counterparts change.
//!
//! Usage: `cargo run -p toolpath-cli --example convert-path-to-jsonl -- <in.path.json> <out.path.jsonl>`

use std::fs;
use toolpath::v1::{Document, Path};

fn main() -> anyhow::Result<()> {
let mut args = std::env::args().skip(1);
let input = args.next().expect("usage: <in.path.json> <out.path.jsonl>");
let output = args
.next()
.expect("usage: <in.path.json> <out.path.jsonl>");

let json = fs::read_to_string(&input)?;
let doc = Document::from_json(&json)?;
let path: Path = match doc {
Document::Path(p) => p,
_ => anyhow::bail!("{input}: not a Path document"),
};
let jsonl = path.to_jsonl_string()?;
fs::write(&output, jsonl)?;
println!("wrote {output}");
Ok(())
}
1 change: 1 addition & 0 deletions crates/toolpath-cli/src/cmd_incept.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ mod tests {
id: "test-path".into(),
base: None,
head: "step-002".into(),
graph_ref: None,
},
steps: vec![
Step {
Expand Down
11 changes: 5 additions & 6 deletions crates/toolpath-cli/src/cmd_merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,17 @@ pub fn run(inputs: Vec<String>, title: Option<String>, pretty: bool) -> Result<(
let mut all_paths = Vec::new();

for input in &inputs {
let content = if input == "-" {
let doc = if input == "-" {
use std::io::Read;
let mut buf = String::new();
std::io::stdin()
.read_to_string(&mut buf)
.context("Failed to read from stdin")?;
buf
Document::from_json(&buf).with_context(|| format!("Failed to parse {:?}", input))?
} else {
std::fs::read_to_string(input).with_context(|| format!("Failed to read {:?}", input))?
crate::io::read_document_auto(std::path::Path::new(input))?
};

let doc = Document::from_json(&content)
.with_context(|| format!("Failed to parse {:?}", input))?;

extract_paths(doc, &mut all_paths);
}

Expand Down Expand Up @@ -55,6 +52,7 @@ fn extract_paths(doc: Document, paths: &mut Vec<PathOrRef>) {
id: format!("path-{}", step_id),
base: None,
head: step_id,
graph_ref: None,
},
steps: vec![s],
meta: None,
Expand Down Expand Up @@ -95,6 +93,7 @@ mod tests {
id: id.to_string(),
base: Some(Base::vcs("github:org/repo", "abc123")),
head,
graph_ref: None,
},
steps,
meta: Some(PathMeta {
Expand Down
1 change: 1 addition & 0 deletions crates/toolpath-cli/src/cmd_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ mod tests {
id: "test-path".to_string(),
base: None,
head: "step-002".to_string(),
graph_ref: None,
},
steps: vec![init_step, append_step],
meta: None,
Expand Down
10 changes: 5 additions & 5 deletions crates/toolpath-cli/src/cmd_query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::{Context, Result};
use anyhow::Result;
use clap::Subcommand;
use std::path::PathBuf;
use toolpath::v1::{Document, query};
Expand Down Expand Up @@ -59,10 +59,8 @@ pub fn run(op: QueryOp, pretty: bool) -> Result<()> {
}
}

fn read_doc(path: &PathBuf) -> Result<Document> {
let content =
std::fs::read_to_string(path).with_context(|| format!("Failed to read {:?}", path))?;
Document::from_json(&content).with_context(|| format!("Failed to parse {:?}", path))
fn read_doc(path: &std::path::Path) -> Result<Document> {
crate::io::read_document_auto(path)
}

fn extract_steps(doc: &Document) -> (&[toolpath::v1::Step], Option<&str>) {
Expand Down Expand Up @@ -175,6 +173,7 @@ mod tests {
id: "p1".into(),
base: Some(Base::vcs("github:org/repo", "abc")),
head: "s3".into(),
graph_ref: None,
},
steps: vec![s1, s2, s2a, s3],
meta: None,
Expand Down Expand Up @@ -213,6 +212,7 @@ mod tests {
id: "p1".into(),
base: None,
head: "s1".into(),
graph_ref: None,
},
steps: vec![s1],
meta: None,
Expand Down
17 changes: 7 additions & 10 deletions crates/toolpath-cli/src/cmd_render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,17 @@ fn run_dot(
show_timestamps: bool,
highlight_dead_ends: bool,
) -> Result<()> {
let content = if let Some(path) = &input {
std::fs::read_to_string(path).with_context(|| format!("Failed to read {:?}", path))?
let doc = if let Some(path) = &input {
crate::io::read_document_auto(path)?
} else {
use std::io::Read;
let mut buf = String::new();
std::io::stdin()
.read_to_string(&mut buf)
.context("Failed to read from stdin")?;
buf
Document::from_json(&buf).context("Failed to parse Toolpath document")?
};

let doc = Document::from_json(&content).context("Failed to parse Toolpath document")?;

let options = toolpath_dot::RenderOptions {
show_files,
show_timestamps,
Expand All @@ -114,19 +112,17 @@ fn run_md(
detail: &str,
front_matter: bool,
) -> Result<()> {
let content = if let Some(path) = &input {
std::fs::read_to_string(path).with_context(|| format!("Failed to read {:?}", path))?
let doc = if let Some(path) = &input {
crate::io::read_document_auto(path)?
} else {
use std::io::Read;
let mut buf = String::new();
std::io::stdin()
.read_to_string(&mut buf)
.context("Failed to read from stdin")?;
buf
Document::from_json(&buf).context("Failed to parse Toolpath document")?
};

let doc = Document::from_json(&content).context("Failed to parse Toolpath document")?;

let detail = match detail {
"full" => toolpath_md::Detail::Full,
_ => toolpath_md::Detail::Summary,
Expand Down Expand Up @@ -162,6 +158,7 @@ mod tests {
id: "p1".into(),
base: None,
head: "s1".into(),
graph_ref: None,
},
steps: vec![s1],
meta: None,
Expand Down
Loading
Loading