vscode-copilot-bridge/AGENTS.md
2025-08-20 19:58:11 +02:00

7.4 KiB
Raw Blame History

AI Agent Contribution Guide

This document gives coding agents (and human maintainers) a clear, opinionated playbook for making safe, coherent, highquality changes to this repository.


1. Project Purpose

Expose GitHub Copilot through a local OpenAIcompatible HTTP bridge inside VS Code. Primary user stories:

  • Run a local /v1/chat/completions endpoint that forwards to Copilot via the VS Code Language Model API.
  • List available Copilot model families through /v1/models.
  • Basic health & availability via /health.

The server is local only (loopback host by default) and is not meant for multitenant or remote exposure.


2. Architecture Snapshot

Layer Key Files Notes
VS Code Extension Activation src/extension.ts Enables/Disables bridge, manages status command.
HTTP Server (Polka) src/http/server.ts Routes + middleware + error handling.
Routes src/http/routes/*.ts health.ts, models.ts, chat.ts.
LM / Copilot Integration src/models.ts Model selection, status updates.
Message Normalization src/messages.ts Shapes user/assistant/system to LM API format.
Status & State src/status.ts, src/state.ts Inmemory server + model state, status bar text.
Config & Logging src/config.ts, src/log.ts Reads bridge.* settings, output channel.
Utilities src/http/utils.ts JSON helpers, typed error responses.

3. Coding Standards

  1. TypeScript Strictness: No any or loose unknown unless inside typed external shim declarations. Use strong VS Code API types (vscode.LanguageModelChat, etc.).
  2. Imports: All imports at file top. No inline import('module') types.
  3. ES Module Style: Use import syntax (even though commonjs output). No require in source except in isolated legacy shims (currently none).
  4. Polka Typings: The custom declaration in src/types/polka.d.ts must stay minimal but strongly typed. Extend only when you need new surface.
  5. Error Handling: Use central onError (server.ts). Avoid swallowing errors; bubble or log via verbose.
  6. Logging: Use verbose() for debug (guarded by config), info() for onetime start messages, error() sparingly (currently not widely used—add only if userfacing severity).
  7. Status Bar: Use updateStatus(kind) with kinds: start | error | success. Initial pending state relies on state.modelAttempted.
  8. Model Selection: Always featuredetect the LM API (hasLMApi). Return early on missing API with clear state.lastReason codes.
  9. Endpoint Stability: Public paths (/health, /v1/models, /v1/chat/completions). Changes require README updates and semantic version bump.
  10. Streaming: SSE contract: multiple data: {chunk} events + final data: [DONE]. Preserve this shape.

4. State & Reason Codes

state.lastReason drives health + status explanations. Allowed values (current):

  • missing_language_model_api
  • copilot_model_unavailable
  • not_found
  • (Potential future: consent_required, rate_limited)

If you introduce new reason codes, update:

  • README.md troubleshooting section
  • handleModelSelectionError
  • Health output expectations

5. Configuration Contract (bridge.*)

See package.json contributes -> configuration. When adding new settings:

  • Provide default
  • Document in README table
  • Use cfg.get(key, default) pattern
  • Add to BridgeConfig and ensure getBridgeConfig() uses satisfies to keep type safety

6. Adding Endpoints

Before adding an endpoint:

  • Justify purpose (user scenario). Keep scope tight; avoid feature creep.
  • Enforce auth (token) uniformly—reuse existing middleware pattern.
  • Return OpenAIcompatible shapes only if endpoint is explicitly an OpenAI analog; otherwise define a minimal JSON schema and document it.
  • Update README (Endpoints section) and bump version (PATCH or MINOR depending on scope).

7. Versioning & Releases

  • Patch: bug fixes, doc updates, internal refactors.
  • Minor: new endpoint, new config option, new visible status semantics.
  • Major (future if ever): breaking API changes (endpoint removal, payload contract changes).

Use npm version <type> then rebuild & (optionally) package VSIX.


8. Logging Guidelines

Use Function Example
Startup/oneoff info info() Bound address, model availability summary
Debug/verbose flow verbose() Perrequest logging, selection outcomes, SSE lifecycle
Serious error (rare) error() Unrecoverable initialization failure

Avoid highvolume logs in hot loops. Guard truly verbose details behind feature flags if needed.


9. Performance & Concurrency

  • Concurrency limit enforced in /v1/chat/completions before model call; maintain early 429 path.
  • Streaming is async iteration; avoid buffering entire response unless stream: false.
  • Do not introduce global locks; keep perrequest ephemeral state.

10. Security

  • Must not widen default host binding without explicit config.
  • All non-health/model/chat endpoints (future) must preserve token auth.
  • Never log bearer tokens or raw user messages verbatim if sensitive; current design logs only structural info.

11. Testing Philosophy (Future)

Tests are currently absent. If adding:

  • Unit: message normalization, model selection error categorization.
  • Integration (optional): spin up server with mock LM API (abstract LM provider behind interface for test harness).

Keep tests deterministic (no real network LM calls).


12. AI Agent Change Workflow

  1. Scan: Read related files (avoid editing blindly). Use grep/search for symbol impact.
  2. Plan: List concrete steps & affected files; ensure config/docs alignment.
  3. Edit: Minimal diffs; avoid formatting unrelated sections.
  4. Validate: npm run compile must pass. (If adding tests later: run them.)
  5. Docs: Update README + this file if contracts change.
  6. Status: Summarize what changed, why, and any followups.

Never leave the codebase with failing type checks.


13. Common Pitfalls

Pitfall Avoidance
Using any for quick fixes Introduce proper interface / generic or refine existing type guard
Forgetting health/status synchronization Update state.lastReason & call updateStatus consistently
Adding silent failure paths Always log via verbose() or propagate error to onError
Breaking SSE spec Maintain final data: [DONE] sentinel
Undocumented reason codes Update troubleshooting section immediately

14. Future Enhancements (Backlog Ideas)

  • Graceful shutdown hook (capture SIGINT in dev host context if feasible)
  • Adaptive model selection (prefer family ordering / scoring)
  • Rate limit headers (e.g., X-RateLimit-Remaining)
  • Optional request timeout support
  • Structured logging (JSON) behind a flag
  • Basic test harness / mock LM provider

(Do not implement without explicit issue creation & approval.)


15. Style & Formatting

  • Rely on TypeScript compiler; no implicit any.
  • Prefer const and readonly arrays where practical.
  • Use nullish coalescing & optional chaining.
  • Use descriptive variable names (shown, availability, etc.).

16. When in Doubt

If a change touches:

  • Endpoint contracts
  • Security (auth / binding)
  • Status semantics

…then treat it as a feature change and document thoroughly.


Happy bridging!