Conversation
Add full session parsing for Factory AI's Droid CLI (factory.ai). Reads JSONL sessions from ~/.factory/sessions/ with companion .settings.json for model/token metadata. Parses Create/Read/Edit/Execute/Bash/LS tool calls, MCP tools, thinking blocks, and todo_state events. Supports native resume via `droid -s <id>` and cross-tool handoff in both directions. All 7 integration points wired: types, parser, barrel export, session index, resume commands, markdown labels, and CLI UI.
Add createDroidFixture() with realistic JSONL + settings.json data. Add Droid-specific parser tests (message extraction, tool_use filtering, session_start/todo_state skipping). Update all test files to include droid in Record<SessionSource, ...> maps. Conversion paths: 5×4=20 → 6×5=30.
- Bump version 2.6.7 → 2.7.0 - Add postinstall message announcing Droid support - Update README: add Droid to feature list, extraction table, storage table, quick-resume examples - Create CHANGELOG.md with 2.7.0 release notes - Update CLAUDE.md to reflect 6 supported tools
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughThis pull request introduces Factory Droid as a sixth supported tool integration, adding session parsing, context extraction, CLI commands, test coverage, and documentation. Version bumped to 2.7.0 with postinstall message updates. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as CLI / User
participant Parser as parseDroidSessions()
participant FS as File System
participant SessionData as JSONL Sessions
participant Extractor as extractDroidContext()
participant Markdown as generateHandoffMarkdown()
CLI->>Parser: Request Droid sessions
Parser->>FS: Scan ~/.factory/sessions/
Parser->>FS: Read .settings.json (model, tokens, timing)
FS-->>Parser: Settings loaded
Parser->>SessionData: Open session.jsonl
SessionData-->>Parser: Parse session_start event
Parser->>SessionData: Extract messages & events
SessionData-->>Parser: Collect tool_use/tool_result, todo_state
Parser-->>CLI: UnifiedSession[] returned
CLI->>Extractor: Extract context for session
Extractor->>SessionData: Read all events
Extractor->>Extractor: Filter messages (exclude system)
Extractor->>Extractor: Extract tool summaries (files, shell)
Extractor->>Extractor: Parse pending tasks from todo_state
Extractor->>Markdown: Generate handoff markdown
Markdown-->>Extractor: Formatted handoff text
Extractor-->>CLI: SessionContext (notes, messages, tasks, markdown)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes This introduces substantial new parser logic (508 lines in droid.ts) with intricate event parsing, tool data extraction, and session metadata handling. The breadth of file modifications across types, utilities, CLI, and test infrastructure—combined with integration points requiring consistent thread-through—demands careful validation of each integration path and verification that Droid sessions flow correctly through the entire context extraction pipeline. Poem
✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
🟡 Missing droid case in e2e test runTool causes throw when droid is used as target
The runTool function in src/__tests__/e2e-conversions.test.ts has a switch statement that handles claude, gemini, codex, opencode, and copilot, but is missing a case 'droid':. The default branch throws new Error('Unknown tool: droid').
Impact Details
Since droid was added to ALL_SOURCES at line 27, the test loop at lines 192-248 will attempt to use droid as both a source and a target. When droid is the target, runTool('droid', ...) is called and hits the default throw at line 111.
While this test file is excluded from CI via vitest.config.ts (pattern **/e2e*), it's still a test that someone would run manually per the PR description. All 5 conversion paths targeting droid (e.g. claude → droid, gemini → droid, etc.) will fail with an unhandled error.
(Refers to lines 110-111)
Was this helpful? React with 👍 or 👎 to provide feedback.
| rl.on('line', (line) => { | ||
| linesRead++; | ||
| if (linesRead > 100) { | ||
| rl.close(); | ||
| stream.close(); | ||
| return; | ||
| } |
There was a problem hiding this comment.
🔴 lastTimestamp truncated to first 100 lines causes incorrect updatedAt for long sessions
The parseSessionInfo function reads only the first 100 lines of a Droid JSONL file (line 173), but tracks lastTimestamp as it goes (line 190). For sessions with more than 100 messages, lastTimestamp will be set to the timestamp of the ~100th message — not the actual last message in the file.
Root Cause and Impact
At src/parsers/droid.ts:268, updatedAt is set from lastTimestamp:
const updatedAt = lastTimestamp ? new Date(lastTimestamp) : fileStats.mtime;The fallback fileStats.mtime would be accurate, but it's only used when lastTimestamp is empty. For any session with at least one message in the first 100 lines, lastTimestamp will be non-empty but stale — it reflects the timestamp at line ~100, not the actual end of the session.
Since sessions are sorted by updatedAt descending (src/parsers/droid.ts:290), long Droid sessions will appear older than they actually are in the session list. A session that was active 5 minutes ago but has 200+ messages could appear as if it was last active hours ago.
The Claude parser avoids this by not extracting timestamps from the JSONL at all — it uses fileStats.mtime for updatedAt (src/parsers/claude.ts:176-177).
Fix: Either read the entire file for lastTimestamp, or use fileStats.mtime as updatedAt (matching the Claude parser pattern), or only use lastTimestamp from parseSessionInfo for createdAt/firstTimestamp and always use fileStats.mtime for updatedAt.
Prompt for agents
In src/parsers/droid.ts, the parseSessionInfo function (lines 155-213) reads only the first 100 lines but tracks lastTimestamp, which is then used as updatedAt at line 268. For sessions longer than 100 lines, this produces a stale updatedAt. Fix by changing line 268 to always use fileStats.mtime for updatedAt, matching the Claude parser pattern:
Change line 268 from:
const updatedAt = lastTimestamp ? new Date(lastTimestamp) : fileStats.mtime;
To:
const updatedAt = fileStats.mtime;
Alternatively, remove lastTimestamp tracking from parseSessionInfo entirely since it's unreliable with the 100-line limit, and update the return type accordingly.
Was this helpful? React with 👍 or 👎 to provide feedback.
Rewrote the entire README to read like an actual developer wrote it: - Punchier intro that leads with the problem, not a feature list - Collapsed the 14×14 checkmark matrix into one sentence - Cut 430→238 lines by removing redundancy and AI-doc patterns - Added Community Contributions section referencing #1, #3, #4, #14 - Documented the 7 new agents (Amp, Kiro, Crush, Cline, Roo Code, Kilo Code, Antigravity) and bugs fixed in this round - Prose over bullet spam, natural flow over exhaustive structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Hey — this adds full support for Factory AI's Droid CLI as the 6th tool in
continues.What changed
Droid stores sessions as JSONL files at
~/.factory/sessions/<workspace-slug>/with a companion.settings.jsonfor model and token metadata. The format turned out to be very close to Claude Code's — Anthropic-styletool_use/tool_resultcontent blocks — so the parser was straightforward to write.New parser (
src/parsers/droid.ts)Handles all the event types I found in real Droid sessions:
session_start— session ID, title, cwd, ownermessage— user/assistant turns withtext,tool_use,tool_result, andthinkingcontent blockstodo_state— extracts pending tasks from Droid's built-in todo trackingcompaction_state— silently skipped (context window management)Tool calls mapped to
SummaryCollectorcategories:Create→write_file,Read→read_file,Edit/ApplyPatch→edit_fileExecute/Bash→shell,LS→ directory listingcontext7___query-docs) → per-tool categoriesTodoWrite→ skipped (internal bookkeeping)Token usage and model info come from the companion
.settings.jsonrather than the JSONL stream.Everything else
All 7 integration points updated:
SessionSourcetype, parser barrel, session index, resume commands (droid -s <id>), markdown labels, CLI colors + quick-resume subcommand.Testing
Version bump
2.6.7 → 2.7.0 (new platform = minor version). Added postinstall message so people know about Droid support when they upgrade.
Test plan
pnpm build— clean compilepnpm test— 84/84 passcontinues list --source droid— discovers real sessionscontinues scan— shows droid in source breakdownSummary by CodeRabbit
Release Notes v2.7.0
New Features
Documentation
Tests
Chores