feat: bulk session export with filtering for SFT datasets - #81
feat: bulk session export with filtering for SFT datasets#81kannupriyakalra wants to merge 1 commit into
Conversation
Adds a first-class bulk export command and API endpoint.
Backend — src/export.ts
- filterSessions(): source / date-range / repo / min-turns / min-tokens
- computeQuality(): 0-100 score (log-scaled turns + duration + no-error bonus)
- formatAsOpenAI(): { messages: [{role, content}] }
- formatAsShareGPT(): { conversations: [{from, value}] }
- bulkExport(): orchestrates filter + format, returns lines + skip stats
- Thinking blocks and tool calls stripped by default; --include-tools keeps them
API — GET /api/export (src/server.ts)
?source, ?from, ?to, ?repo, ?min_turns, ?min_tokens, ?format, ?include_tools
Response: application/x-ndjson
CLI — copilot-lens export (src/cli-export.ts + src/cli.ts)
Same filter flags as the API plus -o/--output for file output.
Stats written to stderr so piped NDJSON stays clean.
Tests — 47 unit tests, all 153 pass. Zero TS errors.
Closes #71
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Verification: feat: bulk session export with filtering for SFT datasetsVerdict: PASS Claim: New Method: Built from Steps
Findings
|
Summary
Closes #71 — bulk session export with filtering for SFT / fine-tuning datasets.
Turns the full session archive into NDJSON fine-tuning data in one command, with filters for source, date range, repo, and quality signals. No new dependencies.
What was added
src/export.ts— filter + format corefilterSessions()computeQuality()formatAsOpenAI(){ messages: [{role, content}] }— OpenAI fine-tuning API formatformatAsShareGPT(){ conversations: [{from, value}] }— Axolotl / LLaMA-Factory formatbulkExport()Thinking blocks always stripped. Tool calls stripped by default;
include_toolskeeps them.GET /api/exportResponse:
application/x-ndjson— first line is a comment with summary stats, then one JSON record per session.sourceallcli | vscode | claude-code | allfromtorepogitRootorcwdmin_turns1min_tokensformatopenaiopenai | sharegptinclude_tools01to keep tool-call eventscopilot-lens exportCLIStats go to stderr; NDJSON goes to stdout — safe to pipe.
Record shapes
OpenAI:
{ "session_id": "abc123", "source": "claude-code", "created_at": "2025-06-01T10:00:00Z", "repo": "/projects/myrepo", "session_quality": { "score": 72, "turn_count": 8, "has_errors": false, "duration_ms": 420000 }, "messages": [ { "role": "user", "content": "Fix the auth bug" }, { "role": "assistant", "content": "I found the issue in session.ts..." } ] }ShareGPT:
{ "conversations": [ { "from": "human", "value": "Fix the auth bug" }, { "from": "gpt", "value": "I found the issue..." } ] }Tests (
src/__tests__/export.test.ts)47 unit tests covering all filter combinations, quality score bounds/ordering, format shape, thinking-block stripping, empty-content skipping, tool-event handling, and all CLI arg parsing. All 153 tests pass. Zero TypeScript errors. Clean build.
Test plan
copilot-lens export --help→ prints usagecopilot-lens export→ NDJSON + stats to stderrcopilot-lens export -o sft.jsonl→ file written, stats on stderr onlycopilot-lens export --min-turns 5→ fewer records than unfilteredcopilot-lens export --format sharegpt→conversationskey instead ofmessagesGET /api/export→application/x-ndjson, comment + recordsGET /api/export?min_turns=999→ comment line only, 0 data linesGET /api/export?format=sharegpt→ ShareGPT-shaped records🤖 Generated with Claude Code