feat: opencode + cursor-agent adapters (sqlite + transcripts)#28
Merged
0bserver07 merged 1 commit intomainfrom May 1, 2026
Merged
feat: opencode + cursor-agent adapters (sqlite + transcripts)#280bserver07 merged 1 commit intomainfrom
0bserver07 merged 1 commit intomainfrom
Conversation
Adds two beta-flagged source adapters bringing supported provider count
to 8/16 from the codeburn catalog.
OpenCode (STACKUNDERFLOW_BETA_OPENCODE=1):
- Multi-DB discovery under $XDG_DATA_HOME/opencode/ (or
~/.local/share/opencode/) — scans for opencode*.db files.
- Reads session / message / part tables; joins parts onto messages to
assemble content_text and tool names.
- Cross-DB session_id encoding: f"{db_basename}:{session.id}" so two
DB files with overlapping inner UUIDs don't collide.
- Token mapping: input_tokens=tokens.input, output_tokens=tokens.output
+ tokens.reasoning, cache_read_tokens=tokens.cache.read,
cache_create_tokens=tokens.cache.write.
- Embedded message.cost stamped onto record.raw["embedded_cost"] for
parity checks against the recomputed value.
Cursor Agent (STACKUNDERFLOW_BETA_CURSOR_AGENT=1):
- Hybrid adapter reading transcripts from
~/.cursor/projects/{project}/agent-transcripts/.
- Two formats auto-detected by extension: legacy text (user: / A: /
[Tool call] / [Tool result] markers) and Composer 2 JSONL.
- Tokens estimated as len(text)//4; every Record gets
record.raw["cost_source"]="estimated".
- Optional SQLite metadata enrichment from
~/.cursor/ai-tracking/ai-code-tracking.db (conversation_summaries
table) for the model name; falls back to "cursor-agent" literal.
- seq is byte offset for both formats.
Pricers (registered in infra/providers/__init__.py):
- OpenCodePricer: claude-* → AnthropicPricer, gpt-* / codex-* →
OpenAIPricer, unknown → None. supports_per_message_tokens() = True.
- CursorAgentPricer: claude-* / gpt-* delegation, literal cursor-agent
fallback returns None. supports_per_message_tokens() = False
(estimated counts).
Both adapters default OFF. macOS-only for v1 on Cursor Agent; OpenCode
is OS-portable via XDG_DATA_HOME. codeburn-catalog §11 / §5.
Tests: 527 → 586 (59 new), all green. Lint clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
a1a770a to
386a8bf
Compare
0bserver07
added a commit
that referenced
this pull request
May 1, 2026
Wave 3 closes the codeburn parity gap. Adds 12 new beta adapters across five PRs covering all remaining providers in codeburn's catalog: - #27 KiloCode, Roo Code (Cline parser reuse) - #28 OpenCode (SQLite session/message/part), Cursor Agent (text+JSONL+SQLite) - #29 Qwen, Gemini (JSONL with normalization) - #30 Copilot (legacy + VS Code transcripts), Codeium (discovery stub), Continue (defensive SQLite parser) - #31 Droid, Kiro, OpenClaw, Pi/OMP (JSONL family) All beta-flagged off by default. 805 backend tests passing (was 527 in v0.4.0). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
Two new beta-flagged source adapters land in this PR, taking the StackUnderflow supported provider count to 8 of 16 from the codeburn catalog (this PR alone).
stackunderflow/adapters/opencode.py, gated bySTACKUNDERFLOW_BETA_OPENCODE=1) — multi-DB discovery under$XDG_DATA_HOME/opencode/(or~/.local/share/opencode/); readssession/message/parttables; encodes session id asf"{db_basename}:{session.id}"to avoid cross-DB UUID collisions; collapses the 5-key OpenCode token shape onto our canonical 4-key shape (reasoning folds into output,cache.{read,write}map tocache_read/cache_create); embeddedmessage.costis stamped onrecord.raw["embedded_cost"]for parity checks.stackunderflow/adapters/cursor_agent.py, gated bySTACKUNDERFLOW_BETA_CURSOR_AGENT=1) — hybrid: reads transcripts from~/.cursor/projects/{project}/agent-transcripts/in two formats (legacy text withuser:/A:/[Tool call]markers, and Composer 2 JSONL), auto-detected by extension. An optional SQLite attribution DB (~/.cursor/ai-tracking/ai-code-tracking.db,conversation_summariestable) enriches the model name; missing DB falls back to"cursor-agent". Tokens are estimated aslen(text)//4and every Record carriesrecord.raw["cost_source"]="estimated".seqis the byte offset of the line / record start so resume works across both formats.infra/providers/__init__.py.OpenCodePricerandCursorAgentPricerroute by model prefix:claude-*→AnthropicPricer,gpt-*/codex-*→OpenAIPricer, unknown →None(cost layer surfaces "no rate" rather than mispricing).OpenCodePricer.supports_per_message_tokens()isTrue;CursorAgentPricerisFalse(estimated tokens).XDG_DATA_HOME. Adapter docstring +_beta_enabledwiring updated instackunderflow/adapters/__init__.py.Test plan
pytest tests/ -q— 586 passed, 2 skipped (baseline was 527; 59 new tests covering both adapters via targeted assertions and the inheritedAdapterContractmixin, plus pricer routing tests for each provider).ruff check stackunderflow/ --select E,F --exclude="*/build.py"— clean.STACKUNDERFLOW_BETA_OPENCODE=1 STACKUNDERFLOW_BETA_CURSOR_AGENT=1 python -c "from stackunderflow.adapters import registered; print([a.name for a in registered()])"→['claude', 'codex', 'opencode', 'cursor-agent'].CHANGELOG
[Unreleased]### Addedupdated with one entry covering both adapters, the SQLite + multi-format complexity, env vars, and thecost_source/embedded_coststamps.🤖 Generated with Claude Code