Skip to content

feat(connectors): add Codebuff (Manicode) connector#6

Closed
anandghegde wants to merge 2 commits intoDicklesworthstone:mainfrom
anandghegde:feat/codebuff-connector
Closed

feat(connectors): add Codebuff (Manicode) connector#6
anandghegde wants to merge 2 commits intoDicklesworthstone:mainfrom
anandghegde:feat/codebuff-connector

Conversation

@anandghegde
Copy link
Copy Markdown

Summary

Adds Codebuff (formerly Manicode) as a first-class connector, bringing FAD's supported-agent count to 22. Implementation follows the existing single-file connector pattern established by aider.rs and amp.rs.

Storage layout

Codebuff persists per-chat history under (the legacy manicode directory name is still used on disk by the CLI even after the rebrand):

~/.config/manicode/                       # legacy name still used on disk
  projects/<projectBasename>/
    chats/<chatId>/
      chat-messages.json                  # serialized ChatMessage[]
      run-state.json                      # SDK RunState snapshot (optional)
  • chatId is the chat's ISO-8601 timestamp with : replaced by -.
  • The connector 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 (and the legacy MANICODE_DATA_DIR) overrides the base directory.
  • Newer builds may use ~/.config/codebuff — both layouts are accepted.

Layout reverse-engineered from getagentseal/codeburn#124.

What's new

  • src/connectors/codebuff.rs — new connector, ~310 lines impl + 12 unit tests:

    • find_chat_files walks all known bases at max_depth=6 and only accepts paths that have a chats/ ancestor (to avoid false positives from arbitrary chat-messages.json files).
    • Tolerant parser accepts both bare ChatMessage[] and { "messages": [...] } shapes; ISO-8601-or-epoch timestamps; aliased role names (human/ai/function/tool_result) normalized to the canonical {user, assistant, system, tool} set; multipart content blocks via the shared flatten_content helper.
    • Per-message credits (Codebuff bills in credits, not tokens) preserved into NormalizedMessage.extra for downstream consumers like cass's analytics surface.
    • started_at / ended_at derived from in-message timestamps, falling back to file mtime.
  • src/lib.rs — registers the slug across all the points existing connectors use:

    • KNOWN_CONNECTORS
    • canonical_connector_slug (aliases: manicode, codebuff-cli)
    • env_override_roots — honors CODEBUFF_DATA_DIR / legacy MANICODE_DATA_DIR
    • default_probe_roots
    • default_probe_paths_tilde — emits all 8 candidate locations
    • Crate-root re-export of CodebuffConnector
  • src/connectors/mod.rs — declares pub mod codebuff; and adds the factory entry to get_connector_factories.

  • CHANGELOG.md — Unreleased entry.

Tests

cargo test --features connectors
  • 663 / 663 existing tests still green.
  • 12 / 12 new connectors::codebuff::tests::* tests pass:
    • new_creates_connector
    • find_chat_files_locates_canonical_layout
    • find_chat_files_ignores_unrelated_json (asserts the chats/ ancestor guard)
    • parse_chat_file_extracts_basic_messages
    • parse_chat_file_accepts_messages_wrapper
    • parse_chat_file_uses_run_state_cwd_when_present
    • parse_chat_file_normalizes_aliased_roles
    • parse_chat_file_handles_empty_array
    • parse_chat_file_invalid_json_returns_error
    • parse_chat_file_preserves_credits_in_extra
    • external_id_uses_chat_id_dir
    • scan_returns_empty_when_no_roots_exist

Notes

  • No new dependencies; uses the same serde_json / walkdir / dotenvy already pulled in by the connectors feature.
  • Token extraction is not implemented because Codebuff's local logs canonically don't store token counts — they bill in credits. The credits are preserved in extra.credits so a downstream tool can compute approximate USD via the public $0.01/credit pay-as-you-go rate (the same approach used by getagentseal/codeburn#124).
  • This PR was reviewed against the published storage layout but has not yet been validated against a real Codebuff install — happy to iterate on parser details if maintainers spot anything off.

Companion PR

Adds detection + session scan for Codebuff (formerly Manicode) chat history
stored under ~/.config/manicode/projects/<project>/chats/<chatId>/chat-messages.json
(and the rebranded ~/.config/codebuff layout).

- New connector module: src/connectors/codebuff.rs (~310 lines impl + 12 tests)
- Recovers originating cwd from the sibling run-state.json so sessions group
  by real project path rather than the on-disk sanitized basename
- Walks manicode-dev and manicode-staging channels when present
- Honors CODEBUFF_DATA_DIR (and legacy MANICODE_DATA_DIR) env overrides
- Tolerant parser accepts both bare ChatMessage[] and {messages: [...]} shapes,
  ISO-8601-or-epoch timestamps, and aliased role names (human/ai/function)
- Preserves Codebuff's per-message 'credits' field in NormalizedMessage.extra
  for downstream consumers (e.g. cass's analytics surface)

Wires the new slug through KNOWN_CONNECTORS, canonical_connector_slug,
env_override_roots, default_probe_roots, default_probe_paths_tilde,
get_connector_factories, and the crate-root re-exports.

All 663 existing tests still pass; 12 new tests cover discovery, parsing,
malformed input, RunState cwd recovery, and credits preservation.

Storage layout reverse-engineered from getagentseal/codeburn PR #124.
@anandghegde anandghegde force-pushed the feat/codebuff-connector branch from e7fffb6 to 4b9bf78 Compare May 1, 2026 11:24
Real-world Codebuff run-state.json files store the originating cwd at
`sessionState.fileContext.cwd` (with `projectRoot` as a sibling), not
at the top-level `cwd` previously probed. Without this, all sessions
fell back to the sanitized `~/.config/manicode/projects/<basename>`
directory name instead of the real project path.

Validated against a live Codebuff install (19 conversations across 18
projects) — sessions now group by their actual cwd.

- Extend JSON pointer chain in cwd_from_run_state with both
  /sessionState/fileContext/{cwd,projectRoot} and the bare
  /fileContext/{cwd,projectRoot} fallback, plus /projectRoot.
- Add unit test mirroring the real schema.
@anandghegde
Copy link
Copy Markdown
Author

Tested against a live Codebuff install ✅

Validated this branch against a real ~/.config/manicode/ directory tree (18 projects, 19 chat sessions, ~9.5MB of chat-messages.json data).

Findings & one fix pushed:

  • The original cwd_from_run_state JSON-pointer chain (/cwd, /projectPath, /state/cwd, /initialState/cwd) did not match the real schema that Codebuff currently writes — every run-state.json I have on disk stores the cwd at sessionState.fileContext.cwd (with sessionState.fileContext.projectRoot as a sibling). Without this fix all sessions fell back to the on-disk sanitized basename.
  • Pushed commit ca827f2 extending the pointer chain to probe the real path first, plus a unit test mirroring the actual schema.

End-to-end results after the fix:

Metric Result
Sessions discovered 19 / 19 (matches find ~/.config/manicode -name chat-messages.json)
Messages parsed 179
Sessions resolving to real cwd 17 / 19 (the 2 remaining had no run-state.json cwd at all and correctly fell back to the basename)
Full FAD test suite 664 passed / 0 failed
cargo test --features connectors codebuff 13 passed / 0 failed

Sample of recovered project paths (sanitized basename → real cwd):

projects/codex_mac           → /Users/<me>/sandboxes/codex_mac
projects/plex                → /Users/<me>/stash/plex                  (4 sessions)
projects/SFContentPort       → /Users/<me>/sandboxes/SFContentPort
projects/salesnavigatorautomationpoc → /Users/<me>/stash/salesnavigatorautomationpoc
projects/zomato-intelligence → /Users/<me>/stash/zomato-intelligence

Full-text search also exercised end-to-end via cass (cass PR #207) — returns correctly-snippeted Codebuff hits with proper role/credits attribution.

I think this is ready to come out of draft from a correctness standpoint. Happy to tweak naming / split the cwd-fix into a separate commit if you'd prefer.

@anandghegde anandghegde marked this pull request as ready for review May 1, 2026 12:07
@Dicklesworthstone
Copy link
Copy Markdown
Owner

Thanks for the very thorough connector implementation — the storage-layout reverse-engineering, the role-name normalization, the credit-bucket preservation in extra, and the env-var override coverage are all clearly thought through.

Per project policy I don't merge outside contributions, so this PR will get closed without merging. I appreciate you taking the time to write it up at this level of detail; that makes it easy to evaluate the idea on its merits.

Codebuff/Manicode coverage isn't currently on my roadmap, but I've noted the discovery layout (the ~/.config/manicode/projects/<base>/chats/<id>/{chat-messages,run-state}.json shape, the manicode-dev/manicode-staging channels, the CODEBUFF_DATA_DIR/MANICODE_DATA_DIR env overrides, and the move toward ~/.config/codebuff in newer builds) so if I do pick up a 22nd connector, the recon work won't have to be redone.

Companion Dicklesworthstone/coding_agent_session_search#207 will get the same treatment.

Sorry for the dead end on this — appreciated.

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