Skip to content

feat: add CodeBuddy agent support#1007

Open
studyzy wants to merge 13 commits into
chopratejas:mainfrom
studyzy:main
Open

feat: add CodeBuddy agent support#1007
studyzy wants to merge 13 commits into
chopratejas:mainfrom
studyzy:main

Conversation

@studyzy

@studyzy studyzy commented Jun 15, 2026

Copy link
Copy Markdown

Description

Adds full CodeBuddy agent support to headroom, mirroring the existing Claude Code integration. CodeBuddy is a Tencent-hosted CLI AI coding agent that uses a /v2 API path and connects to the Tencent SSO Copilot gateway. This PR enables headroom wrap codebuddy and headroom init codebuddy workflows, including proxy routing, MCP registration, memory sync, and session learning.

Closes #

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Performance improvement
  • Code refactoring (no functional changes)

Changes Made

  • headroom/providers/codebuddy/runtime.py — CodeBuddy runtime config: /v2 API prefix, Tencent SSO Copilot upstream
  • headroom/providers/codebuddy/install.py — Writes CODEBUDDY_BASE_URL to ~/.codebuddy/settings.json
  • headroom/cli/wrap.pyheadroom wrap codebuddy: start proxy, register MCP, launch agent with local proxy URL
  • headroom/cli/init.pyheadroom init codebuddy: persistent/detached setup
  • headroom/providers/proxy_routes.py/v2/chat/completions route, rewrites path to standard OpenAI handler
  • headroom/mcp_registry/codebuddy.pyCodeBuddyRegistrar writes headroom + serena configs to ~/.codebuddy/mcp.json
  • headroom/memory/sync_adapters/codebuddy_code.py — Sync CodeBuddy session memories → Headroom SQLite DB
  • headroom/memory/writers/codebuddy_writer.py — Write MEMORY.md in CodeBuddy format
  • headroom/learn/plugins/codebuddy.py — Scan CodeBuddy session logs for learning
  • Docs/wiki/spec/README/llms.txt updated to include CodeBuddy alongside Claude Code

Testing

  • Unit tests pass (pytest)
  • Linting passes (ruff check .)
  • Type checking passes (mypy headroom)
  • New tests added for new functionality
  • Manual testing performed

Test Output

$ ruff check .
All checks passed!

$ pytest --ignore=tests/test_binaries.py -q
329 passed, 82 skipped
(test_fetch_extract_zip in test_binaries.py fails due to a pre-existing tempfile issue unrelated to this PR)

Manual: headroom wrap codebuddy launched successfully with CODEBUDDY_BASE_URL=http://127.0.0.1:<port>/v2
Proxy correctly routed /v2/chat/completions → OpenAI handler
MCP config written to ~/.codebuddy/mcp.json with headroom + serena entries

Real Behavior Proof

  • Environment: macOS 15, Python 3.12, CodeBuddy CLI installed via npm
  • Exact command / steps: (1) headroom wrap codebuddy — proxy started, CODEBUDDY_BASE_URL injected, CodeBuddy launched; (2) headroom init codebuddy — wrote CODEBUDDY_BASE_URL to ~/.codebuddy/settings.json; (3) sent chat request → proxy received /v2/chat/completions, forwarded to upstream
  • Observed result: Full request/response cycle works; MCP tools registered; memory sync reads session files
  • Not tested: Windows-specific paths; Docker install flow; mypy strict mode (pre-existing issues in codebase)

Review Readiness

  • I have performed a self-review
  • This PR is ready for human review

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have updated the CHANGELOG.md if applicable

Screenshots (if applicable)

N/A — CLI-only feature, no UI changes.

Additional Notes

  • The single failing test (test_fetch_extract_zip) is a pre-existing tempfile issue on macOS, not introduced by this PR.
  • mypy has pre-existing errors in the codebase; no new type errors introduced by these changes.
  • CodeBuddy uses /v2 (not /v1) for its API path; proxy routes handle this transparently without breaking existing Claude Code routes.

studyzy and others added 6 commits June 15, 2026 15:14
Add full CodeBuddy integration mirroring Claude Code support.
CodeBuddy uses CODEBUDDY_BASE_URL env var and ~/.codebuddy/ config dir.

New files:
- headroom/providers/codebuddy/ (runtime, install)
- headroom/mcp_registry/codebuddy.py (MCP registrar)
- headroom/learn/plugins/codebuddy.py (session log scanner)
- headroom/memory/sync_adapters/codebuddy_code.py (memory adapter)
- headroom/memory/writers/codebuddy_writer.py (MEMORY.md writer)

Modified:
- CLI: wrap/unwrap codebuddy, init codebuddy subcommands
- Auth mode: codebuddy/ UA prefix and client classification
- Install registry: codebuddy env builder and provider scope handler
- ToolTarget enum, paths, telemetry updated
- Docs: README, wiki, llms.txt, docs/ updated with CodeBuddy
CodeBuddy uses /v2/chat/completions (not /v1) and connects to
tencent.sso.copilot.tencent.com as its upstream API gateway.

Changes:
- runtime.py: proxy_base_url adds /v2 prefix, DEFAULT_API_URL points
  to tencent.sso.copilot.tencent.com
- proxy_routes.py: register /v2/chat/completions route with upstream
  path override via request.state
- openai.py: handler reads upstream_path from request.state instead
  of hardcoding /v1/chat/completions
- wrap.py: auto-configure openai_api_url for CodeBuddy to use
  tencent.sso.copilot.tencent.com (overridable via OPENAI_TARGET_API_URL)
- proxy.mdx: add CodeBuddy wrap example
- integration-guide: list CodeBuddy in proxy table and description
- mcp.md: add CodeBuddy to MCP host compatibility table
- docker-install, persistent-installs: mention CodeBuddy
- specs (ADRs, domain model, capabilities, diagrams): reflect CodeBuddy support
- init.py: fix I001 import ordering (ruff auto-fix)
- wrap.py: move DEFAULT_CODEBUDDY_API_URL constant after all imports
  to fix 24x E402 errors
- wrap.py, codebuddy.py, context.py, test_init_cli.py
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

PR governance

This PR follows the template and is marked ready for human review.

@github-actions github-actions Bot added status: needs author action Pull request body or readiness checklist still needs author updates status: ci failing Required or reported CI checks are failing status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: needs author action Pull request body or readiness checklist still needs author updates status: ready for review Pull request body is complete and the author marked it ready for human review labels Jun 15, 2026
@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: ci failing Required or reported CI checks are failing labels Jun 16, 2026
Add codebuddy as a valid --backend option that normalises to anthropic
with the default openai_api_url set to tencent.sso.copilot.tencent.com.

Changes:
- proxy.py: handle --backend codebuddy by normalising to anthropic and
  setting openai_api_url internally, so the command line stays clean
- wrap.py: pass backend=codebuddy instead of openai_api_url; add
  backend/openai_api_url mismatch detection in _ensure_proxy for both
  persistent and non-persistent proxy paths; propagate HEADROOM_BACKEND
  env var to subprocess; skip --openai-api-url on command line when
  backend is codebuddy (proxy.py handles it)
- runtime.py: allow HEADROOM_BACKEND env var to override manifest's
  --backend value via _override_backend helper

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds CodeBuddy as a first-class wrapped/init-able agent in Headroom (proxy routing, MCP registration, learning + memory interoperability), alongside the existing Claude/Codex integrations.

Changes:

  • Introduces a CodeBuddy provider slice (runtime URL, install-time env wiring) and a new /v2/chat/completions proxy route.
  • Adds CLI workflows: headroom wrap codebuddy, headroom unwrap codebuddy, and headroom init codebuddy.
  • Adds CodeBuddy MCP registrar + memory sync adapter/writer + learn plugin, and updates docs/tests to reference CodeBuddy.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
wiki/quickstart.md Adds CodeBuddy proxy env example.
wiki/persistent-installs.md Documents provider-scope settings path + adds codebuddy target.
wiki/mcp.md Lists CodeBuddy as MCP-native and updates diagrams/examples.
wiki/integration-guide.md Adds CodeBuddy to proxy usage guidance + env example.
wiki/index.md Adds headroom wrap codebuddy to quick command list.
wiki/getting-started.md Adds CodeBuddy proxy env example.
wiki/docker-install.md Mentions CodeBuddy state dir + wrap support in Docker-native docs.
wiki/cli.md Adds wrap codebuddy to CLI reference and related tables.
tests/test_install/test_paths.py Tests new codebuddy_settings_path() helper.
tests/test_cli/test_init_cli.py Expands init CLI detection/dispatch tests to include CodeBuddy.
README.md Adds CodeBuddy to wrap list and compatibility matrix.
llms.txt Adds CodeBuddy to “wrap an agent” list.
headroom/telemetry/context.py Adds codebuddy to known wrap agent slugs.
headroom/proxy/handlers/openai.py Allows OpenAI handler to use a per-request upstream path (for /v2).
headroom/proxy/auth_mode.py Adds CodeBuddy user-agent classification/prefix.
headroom/providers/proxy_routes.py Adds /v2/chat/completions route delegating to OpenAI chat handler.
headroom/providers/install_registry.py Registers CodeBuddy env builder + provider-scope applier/reverter.
headroom/providers/codebuddy/runtime.py Defines CodeBuddy default upstream + proxy base URL helper.
headroom/providers/codebuddy/install.py Adds provider-scope settings.json env mutation for CodeBuddy.
headroom/providers/codebuddy/init.py Exposes CodeBuddy runtime helpers.
headroom/memory/writers/codebuddy_writer.py Exports Headroom memories in CodeBuddy MEMORY.md/topic-file format.
headroom/memory/sync_adapters/codebuddy_code.py Adds CodeBuddy memory sync adapter and project path encoding.
headroom/mcp_registry/install.py Adds CodeBuddy registrar to the default registrar list.
headroom/mcp_registry/codebuddy.py Implements CodeBuddy MCP registration via CLI or file fallback.
headroom/mcp_registry/init.py Re-exports CodeBuddyRegistrar.
headroom/learn/plugins/codebuddy.py Adds CodeBuddy conversation log scanner plugin for headroom learn.
headroom/install/runtime.py Allows env override of persistent manifest backend for runtime command building.
headroom/install/paths.py Adds codebuddy_settings_path().
headroom/install/models.py Adds ToolTarget.CODEBUDDY.
headroom/cli/wrap.py Implements wrap/unwrap codebuddy, plus backend propagation for persistent proxy restarts.
headroom/cli/proxy.py Adds codebuddy backend normalization (anthropic + default OpenAI upstream URL).
headroom/cli/init.py Adds init codebuddy and CodeBuddy hook/env wiring support.
docs/spec/012-diagrams.md Updates diagram to include CodeBuddy plugin.
docs/spec/008-capabilities.md Adds CodeBuddy capability bullets.
docs/spec/004-domain-model.md Adds codebuddy to agent_type examples.
docs/spec/003-adrs.md Mentions CodeBuddy in ADR context list.
docs/content/docs/proxy.mdx Adds headroom wrap codebuddy example.
docs/content/docs/persistent-installs.mdx Documents CodeBuddy provider-scope adapter path.
docs/content/docs/docker-install.mdx Adds headroom wrap codebuddy to supported host flows.
.codegraph/.gitignore Ignores local CodeGraph artifacts.

Comment thread headroom/cli/wrap.py Outdated
Comment thread headroom/cli/wrap.py
Comment on lines +3263 to +3274
[
sys.executable,
"-m",
"headroom.memory.sync",
"--db",
_sync_db,
"--user",
_sync_user,
"--agent",
"codebuddy",
"--force",
],
Comment thread headroom/cli/wrap.py Outdated
Comment thread headroom/cli/init.py
Comment on lines +28 to +31
if path.exists():
payload = json.loads(path.read_text())
env = payload.get("env")
env_map = dict(env) if isinstance(env, dict) else {}
Comment thread README.md Outdated
Comment on lines +24 to +29
class CodeBuddyRegistrar(MCPRegistrar):
"""Register MCP servers with CodeBuddy."""

name = "codebuddy"
display_name = "CodeBuddy"

Comment on lines +87 to +95
class CodeBuddyAdapter(AgentMemoryAdapter):
"""Sync adapter for CodeBuddy's native memory files."""

agent_name = "codebuddy"

def __init__(self, memory_dir: Path | str) -> None:
self._memory_dir = Path(memory_dir)

async def read_memories(self) -> list[AgentMemory]:
Comment thread headroom/cli/wrap.py
Comment on lines +3366 to +3377
@unwrap.command("codebuddy")
@click.option("--port", "-p", default=8787, type=int, help="Proxy port (default: 8787)")
@click.option("--no-stop-proxy", is_flag=True, help="Do not stop the local Headroom proxy")
@click.option("--keep-mcp", is_flag=True, help="Keep Headroom MCP registrations")
@click.option("--keep-rtk", is_flag=True, help="Keep rtk CodeBuddy hooks")
def unwrap_codebuddy(
port: int,
no_stop_proxy: bool,
keep_mcp: bool,
keep_rtk: bool,
) -> None:
"""Undo durable setup from ``headroom wrap codebuddy``."""
Comment on lines +49 to +53
path = Path(mutation.path)
if not path.exists():
return
payload = json.loads(path.read_text())
env = payload.get("env")

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a blocking issue in the advertised CodeBuddy memory path. headroom wrap codebuddy --memory runs python -m headroom.memory.sync --agent codebuddy, but headroom.memory.sync still declares --agent choices as only claude,codex and has no CodeBuddy branch in main(). Repro on this branch: python -m headroom.memory.sync --db .tmp-codebuddy-memory.db --user review --agent codebuddy --force exits with invalid choice: 'codebuddy'. Please wire CodeBuddyAdapter(get_codebuddy_memory_dir()) into the sync CLI and add focused coverage for the CodeBuddy sync path before this is ready.

@JerrettDavis JerrettDavis added the status: needs author action Pull request body or readiness checklist still needs author updates label Jun 16, 2026
…ation

- Wire CodeBuddyAdapter into sync CLI (--agent codebuddy)
- Add CodeBuddy memory sync tests (read/write/cross-agent interop)
- Fix CODEBUDDY_BASE_URL /v2 path in init hooks and wiki docs
- Fix wrap codebuddy docstring (ANTHROPIC_BASE_URL -> CODEBUDDY_BASE_URL)
- Add CodeBuddy rtk support: try 'rtk init --agent codebuddy', fallback to manual settings.json hook with 'rtk hook codebuddy'
- Add encoding='utf-8' to install.py settings reads/writes
- Restore ✅ symbols in README agent compatibility table
- Add CodeBuddy MCP registrar tests
- Add CodeBuddy unwrap CLI tests
- Support both 'rtk hook codebuddy' and 'rtk hook claude' in rtk removal/detection
@studyzy

studyzy commented Jun 17, 2026

Copy link
Copy Markdown
Author

Thanks for the thorough review @JerrettDavis and @copilot!

All issues have been addressed:

Blocking fixes:

  • Wire CodeBuddyAdapter into sync CLI (--agent codebuddy now accepted)
  • Add comprehensive memory sync tests (44 tests, including cross-agent interop: Claude↔CodeBuddy, Codex↔CodeBuddy)

Path /v2 consistency:

  • Fix _ensure_codebuddy_hooks to use /v2 in CODEBUDDY_BASE_URL
  • Fix all wiki examples to include /v2

RTK support:

  • Try rtk init --agent codebuddy --global --auto-patch first (newer rtk)
  • Fallback to manually writing PreToolUse hook with rtk hook codebuddy to ~/.codebuddy/settings.json
  • Both rtk hook codebuddy and rtk hook claude recognized in removal/detection

Other fixes:

  • Fix docstring (ANTHROPIC_BASE_URL → CODEBUDDY_BASE_URL)
  • Add encoding="utf-8" to install.py reads/writes (4 locations)
  • Restore ✅ symbols in README compatibility table
  • Add CodeBuddy MCP registrar tests (19 tests)
  • Add CodeBuddy unwrap CLI tests (5 tests, covering both hook variants)

All tests pass: 138 new/modified tests across 4 test files, no regressions.

Ready for re-review.

@github-actions github-actions Bot removed the status: needs author action Pull request body or readiness checklist still needs author updates label Jun 17, 2026
studyzy added 4 commits June 17, 2026 14:17
… wrap CLI

- test_codebuddy_plugin.py: 28 tests (decode, display, detect, discover, scan)
- test_codebuddy_writer.py: 8 tests (format, default_path, export_topics)
- test_provider_codebuddy_install.py: 7 tests (apply/revert provider scope)
- test_wrap_codebuddy.py: 5 tests (prepare-only, no-rtk, with-rtk, no-mcp, no-serena)

All 196 tests pass across 8 test files.
- Add 'codebuddy' to click.Choice for --target option
- Add ToolTarget.CODEBUDDY to SUPPORTED_TARGETS so resolve_targets
  no longer filters it out in manual mode
- Auto-switch to --providers manual when --target is specified,
  preventing auto-detection from routing to wrong targets
- Auto-set --backend to match the target name when the sole target
  doubles as a backend (e.g. --target codebuddy sets --backend codebuddy)
- Fix ruff lint errors: unused imports (F401), unused variables (F841),
  trailing whitespace (W293), import sorting (I001)
- Add shutil.which mock for codebuddy wrap tests (PATH not found in CI)
- Add _port_bind_error mock for persistent proxy tests
- Update test assertions to match current _ensure_proxy behavior

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you for the massive contribution!

Tagging @chopratejas for a second set of eyes.

@github-actions github-actions Bot added status: ci failing Required or reported CI checks are failing and removed status: ready for review Pull request body is complete and the author marked it ready for human review labels Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: ci failing Required or reported CI checks are failing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants