Skip to content

feat(providers): add Codebuff provider#124

Open
anandghegde wants to merge 2 commits intogetagentseal:mainfrom
anandghegde:feat/codebuff-provider
Open

feat(providers): add Codebuff provider#124
anandghegde wants to merge 2 commits intogetagentseal:mainfrom
anandghegde:feat/codebuff-provider

Conversation

@anandghegde
Copy link
Copy Markdown

Summary

Adds Codebuff (formerly Manicode) as a first-class provider, moving it off the "Planned" row and onto the supported list. Implementation follows the single-file plugin pattern established by the pi and opencode providers — src/providers/codebuff.ts is 100% of the new runtime code.

Data source

Codebuff persists per-chat history under:

~/.config/manicode/                       # legacy name still used on disk
  projects/<projectBasename>/
    chats/<chatId>/
      chat-messages.json                  # serialized ChatMessage[]
      run-state.json                      # SDK RunState snapshot
  • chatId is the chat's ISO-8601 timestamp with : replaced by -.
  • The provider consults run-state.json to recover the real cwd so sessions group by the originating project directory (not the sanitized folder name).
  • manicode-dev and manicode-staging channels are walked automatically when present.
  • CODEBUFF_DATA_DIR overrides the base directory.

Cost model (important caveat)

Codebuff bills in credits, not tokens. The local chat log records message.credits on completed assistant messages but not token counts (except when Codebuff routed the call through an upstream provider and stashed its RunState with OpenRouter-shaped usage).

This provider therefore uses a two-tier cost resolution:

  1. If the message — or the stashed RunState's last assistant providerOptions.usage — reports real token counts, run those through the existing calculateCost() / LiteLLM pricing engine. Exact match with how the other providers work.
  2. Otherwise, approximate costUSD = credits * USD_PER_CREDIT where USD_PER_CREDIT = 0.01 (Codebuff's public pay-as-you-go rate). This is a conservative upper bound — subscription-plan users will see a slight overstatement, which is less misleading than reporting $0 for an obviously-non-free session.

The rationale is documented inline in src/providers/codebuff.ts.

Tool normalization

Codebuff-native tool names map to the canonical set so the classifier heuristics (Edit-implies-coding, Bash + git pattern implies git, etc.) light up consistently:

Codebuff tool Canonical
read_files Read
code_search Grep
glob, find_files Glob
str_replace Edit
write_file Write
run_terminal_command Bash
spawn_agents Agent
write_todos TodoWrite
browser_logs WebFetch
web_search WebSearch

suggest_followups and end_turn are explicitly ignored — they're not useful signals for task classification.

Files

  • src/providers/codebuff.ts — new single-file provider (discovery, parser, tool/model normalization).
  • src/providers/index.ts — registers Codebuff as a core provider (coreProviders).
  • tests/providers/codebuff.test.ts — 18 tests covering discovery, parsing, multi-turn sessions, providerOptions fallback, dedup, malformed files, and display names.
  • tests/provider-registry.test.ts — updated to assert Codebuff is registered and its tool/model display names.
  • package.json — adds codebuff to the keywords list.
  • README.md — adds Codebuff to the top-line supported-providers blurb, the supported-providers table, the --provider example list, the "How it reads data" section, and the environment-variables table.

Verification

npm install
npm run build       # tsup, clean
npx tsc --noEmit    # no errors
npx vitest run
  • tests/providers/codebuff.test.ts18/18 passed.
  • tests/provider-registry.test.ts11/11 passed (was 9; added 2 for Codebuff tool + model display names).
  • Full suite: 336/337 pass; the one pre-existing failure (tests/day-aggregator.test.ts asserting '2026-04-09' vs '2026-04-10') reproduces identically on main with no Codebuff code — it's a host-timezone sensitivity.

End-to-end against real local data:

$ node dist/cli.js report --provider codebuff --format json -p all \
    | jq '.overview'
{
  "cost": 19.45,
  "calls": 56,
  "sessions": 10,
  "cacheHitPercent": 0,
  "tokens": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
}

10 Codebuff sessions across 5 projects, 56 assistant calls, $19.45 total (1,945 credits × $0.01).

Notes

  • Runtime is pure Node — no new dependencies.
  • Dedup key is codebuff:<chatDir>:<messageId|index>; re-parsing the same session yields zero additional calls.
  • Matches the existing "each provider is one file" contract stated in the Adding a provider README section.

Adds the Codebuff provider (formerly Manicode) as a single-file plugin
under src/providers/codebuff.ts, following the conventions used by the
pi and opencode providers.

Data source:
- Walks ~/.config/manicode/projects/<project>/chats/<chatId>/
- chat-messages.json holds the serialized ChatMessage[]
- run-state.json is consulted to recover the real cwd so sessions group
  by the originating project directory
- manicode-dev and manicode-staging channels are walked automatically
- Honors CODEBUFF_DATA_DIR for a custom root

Cost model:
- Codebuff bills in credits, not tokens. Each completed assistant message
  records credits on message.credits; CodeBurn approximates cost using
  the public PAYG rate ($0.01 / credit) as a conservative upper bound.
- When Codebuff routes a call through an upstream provider and the
  stashed RunState records real token totals (providerOptions.usage or
  providerOptions.codebuff.usage in messageHistory), the LiteLLM-based
  calculation takes precedence.

Tool normalization maps Codebuff-native names (read_files, str_replace,
run_terminal_command, spawn_agents, etc.) to the canonical set used by
the classifier (Read, Edit, Bash, Agent, TodoWrite, ...).

Tests:
- 18 provider tests covering discovery, parsing, multi-turn sessions,
  providerOptions fallback, dedup, malformed files, display names
- provider-registry.test.ts updated to assert codebuff is registered
  and its tool/model display names

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@Qodo-Free-For-OSS
Copy link
Copy Markdown

Hi, The Codebuff provider sets sessionId to only the chat folder basename (chatId), so sessions from different Codebuff channels with the same chatId (and same project) will be merged into a single session during aggregation.

Severity: action required | Category: correctness

How to fix: Include channel in sessionId

Agent prompt to fix - you can give this to your LLM of choice:

Issue description

Codebuff sessionId is currently just chatId (folder basename). Since session discovery walks multiple channels (manicode, manicode-dev, manicode-staging), identical chat IDs can exist in different channels and will be merged together downstream.

Issue Context

Downstream aggregation groups sessions by ${providerName}:${call.sessionId}:${source.project}. If two different Codebuff roots produce the same sessionId and project, the turns will be combined into one session.

Fix Focus Areas

  • src/providers/codebuff.ts[322-325]
    • Change sessionId to incorporate channel/root identity (e.g., sessionId = ${channel}:${chatId}``).
    • Derive channel robustly (avoid join(..., '..') + basename() pitfalls); prefer dirname() repeated or resolve() to normalize before basename().

Suggested implementation sketch

  • Compute channelRoot = dirname(dirname(dirname(dirname(chatDir)))) (chatId -> chats -> project -> projects -> channel).
  • const channel = basename(channelRoot)
  • const sessionId = ${channel}:${chatId}``

Tests

Update/add tests in tests/providers/codebuff.test.ts to assert distinct session IDs when the same chatId exists under different channel roots.


Found by Qodo code review

…channel

Resolves merge conflicts with main (README.md, src/providers/index.ts,
tests/provider-registry.test.ts, package-lock.json) and addresses PR
review feedback from Qodo-Free-For-OSS:

- Codebuff sessionId now includes the channel root name (manicode,
  manicode-dev, manicode-staging) derived from the chat directory
  structure, preventing the same chatId from colliding across channels
  when downstream aggregation keys by (provider, sessionId, project).
- Uses '/' as the channel/chatId separator to avoid clashing with
  src/parser.ts's colon-delimited session key format.
- Adds tests: collision across channels, channel inclusion, and
  fallback when the path doesn't match the expected shape.
- Updates README dedup paragraph to mention Codebuff's strategy.
@anandghegde
Copy link
Copy Markdown
Author

/review

Addressed the previous feedback: sessionId now includes the channel root (derived from the <channel>/projects/<project>/chats/<chatId> path) so the same chatId across manicode, manicode-dev, and manicode-staging no longer collides in downstream aggregation. Used / as the channel/chatId separator to avoid clashing with src/parser.ts's colon-delimited session key. Added regression tests. Please re-review.

anandghegde added a commit to anandghegde/coding_agent_session_search that referenced this pull request May 1, 2026
Wires Codebuff (formerly Manicode) into cass as the 20th supported
coding-agent connector. The on-disk discovery + parser implementation
lives in the upstream franken_agent_detection crate; this PR adds:

- src/connectors/codebuff.rs: thin re-export stub for CodebuffConnector,
  matching the established pattern (see aider.rs / amp.rs).
- src/connectors/mod.rs: registers the new module.
- README.md: adds Codebuff to the top-line supported-providers blurb
  and the 'How it reads data' section, documenting the
  ~/.config/manicode/projects/<project>/chats/<chatId>/chat-messages.json
  layout, the run-state.json cwd recovery, the manicode-dev/staging
  channels, and the CODEBUFF_DATA_DIR / MANICODE_DATA_DIR overrides.
- CHANGELOG.md: Unreleased entry.

Cargo.toml & build.rs note: temporarily pinned at the @anandghegde fork
of franken_agent_detection that carries the companion Codebuff connector
PR. Once the upstream FAD PR lands, the URL/rev should be flipped back
to Dicklesworthstone/franken_agent_detection and bumped to that merge
commit. Both files have a TODO comment pointing at the matching change.

Storage layout reverse-engineered from getagentseal/codeburn#124. Local
'cargo check' on x86_64-apple-darwin is green.
anandghegde added a commit to anandghegde/coding_agent_session_search that referenced this pull request May 1, 2026
Wires Codebuff (formerly Manicode) into cass as the 20th supported
coding-agent connector. The on-disk discovery + parser implementation
lives in the upstream franken_agent_detection crate; this PR adds:

- src/connectors/codebuff.rs: thin re-export stub for CodebuffConnector,
  matching the established pattern (see aider.rs / amp.rs).
- src/connectors/mod.rs: registers the new module.
- README.md: adds Codebuff to the top-line supported-providers blurb
  and the 'How it reads data' section, documenting the
  ~/.config/manicode/projects/<project>/chats/<chatId>/chat-messages.json
  layout, the run-state.json cwd recovery, the manicode-dev/staging
  channels, and the CODEBUFF_DATA_DIR / MANICODE_DATA_DIR overrides.
- CHANGELOG.md: Unreleased entry.

Cargo.toml & build.rs note: temporarily pinned at the @anandghegde fork
of franken_agent_detection that carries the companion Codebuff connector
PR. Once the upstream FAD PR lands, the URL/rev should be flipped back
to Dicklesworthstone/franken_agent_detection and bumped to that merge
commit. Both files have a TODO comment pointing at the matching change.

Storage layout reverse-engineered from getagentseal/codeburn#124. Local
'cargo check' on x86_64-apple-darwin is green.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants