Merged
Conversation
|
🔍 Preview deployed: https://88ef161e.toolpath.pages.dev |
akesling
approved these changes
Apr 17, 2026
Contributor
akesling
left a comment
There was a problem hiding this comment.
LGTM
Seems a reasonable enough first pass. I expect there's some low hanging fruit for some type reuse across providers and perhaps some better patterns to organize, but best to get this into the repo to help inform current work.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add
toolpath-gemini— derive Toolpath documents from Gemini CLI conversationsReads Gemini CLI conversation logs from
~/.gemini/tmp/<project>/chats/and projects them onto the provider-agnostictoolpath-convotypes andtoolpath::v1::Path. Mirrors thetoolpath-claudesurface. Wiresderive geminiandlist geminiintotoolpath-cli.Design
Session layout. Main chat at
chats/session-<timestamp>-<short>.json(kind: "main") plus optional sibling<full-uuid>/dir holdingkind: "subagent"chats.read_conversationloads the main file and folds sub-agent chats intoDelegatedWorkon the parenttaskinvocation —turnsis populated (richer thantoolpath-claude, whose sub-agent turns stay empty).Three-layer fidelity.
ChatFile/Conversation— raw on-disk schemaConversationView— provider-agnostic projectionTurn.extra["gemini"])toolpath::v1::Path— provenance digestRound-trip at the
ChatFilelayer is guaranteed byOption<Vec<T>>on optional list fields (absent vs[]preserved),GeminiRole::Other(String)catch-all for unknown roles,Option<serde_json::Value>on polymorphicresultDisplay, and#[serde(flatten)] extraat both chat and message levels for forward-compat.RFC "at least one perspective." File-write
ArtifactChangepopulates bothraw(Gemini'sresultDisplay.fileDiff, or a hand-rolled hunk) andstructural(typedgemini.write_file/gemini.replaceop with args).Non-file-write tool args preserved. Shell commands, grep patterns, read targets, task prompts all land in
structural.tool_calls[].summaryofconversation.appendsteps — no data loss from derivation.Field mapping
sessionIdgemini://<uuid>artifact URI +path.idshort formdirectories[0]path.base.uri(file://…)change["gemini://…"].structural.text(verbatim)infomessageactor: "system:gemini-cli"modelagent:gemini-3-flash-preview) +meta.actorsstructural.tool_calls[].{name,status}structural.tool_calls[].summarywrite_file/replacebodiesraw(unified diff) +structural(typed op, args, byte count)resultDisplay.fileDiffrawperspective on the file changethoughts,tokens.*, tool resultsConversationView.Turn(not in the Path digest;--include-thinkingopts into thoughts inline)18 messages → 18 steps, 1:1. Every parent reference resolves;
headvalid.Test plan
cargo test --workspace— all green (129 unit + 3 fixture + 9 round-trip + 4 doc tests intoolpath-gemini)cargo clippy --workspace -- -D warnings— cleanpath derive gemini … | path validateon real local session dataChatFileserdeFollow-ups
toolpath-claudehas the same absent-vs-empty / null-dropping bug class; confirmed by running the round-trip check against real Claude JSONL (isSidechaininjected,parentUuid: nulldropped). Port the fix.toolpath-claude's watcher parity.Path.meta.extra["gemini"]["chat_file"]side-channel forPath→ChatFilereversibility (the digest is one-way today).