src — copilot
src — copilot
The src/copilot/copilot-proxy.ts module provides a robust, configurable HTTP proxy server designed to emulate the GitHub Copilot API. Its primary purpose is to intercept and process AI completion requests, delegating the actual generation of completions to a custom, pluggable handler. This allows other modules to integrate their own AI models or logic while benefiting from the proxy's built-in features like authentication, rate limiting, and standardized API responses.
Overview
The CopilotProxy class creates a local HTTP server that listens for incoming requests, primarily targeting the /v1/completions endpoint. It acts as a middleware layer, handling common concerns such as:
- API Emulation: Mimics key Copilot API endpoints (
/v1/completions,/v1/models,/health). - Authentication: Supports bearer token authentication.
- Rate Limiting: Implements IP-based request rate limiting.
- Request Parsing & Validation: Parses incoming JSON bodies and validates essential fields like
prompt. - Completion Delegation: Forwards validated completion requests to a user-defined
onCompletioncallback. - Error Handling: Provides standardized JSON error responses for various issues (auth, rate limit, bad request, internal errors).
This module is crucial for integrating custom AI completion services into environments that expect a Copilot-compatible API.
Core Components
CopilotProxy Class
The central component of this module. CopilotProxy is an EventEmitter, allowing consumers to subscribe to lifecycle events like listening (when the server starts) and error (for unhandled server errors).
Key Methods:
constructor(config: CopilotProxyConfig): Initializes the proxy with the provided configuration. Sets up default values and a timer for rate limit cleanup.start(): Promise: Asynchronously starts the HTTP server, binding it to the configured host and port. Emits alisteningevent on success.stop(): Promise: Asynchronously stops the HTTP server and clears the rate limit cleanup timer.handleRequest(req: IncomingMessage, res: ServerResponse): Promise: The core request handler. This private method orchestrates authentication, rate limiting, endpoint routing, and completion processing.authenticate(req: IncomingMessage): boolean: Checks theAuthorizationheader against the configuredauthToken.checkRateLimit(clientIp: string): boolean: Implements a token-bucket-like rate limiting mechanism per client IP.parseBody(req: IncomingMessage): Promise: Reads and buffers the incoming request body, enforcing aMAX_BODY_SIZElimit (10MB).getRequestCount(): number: Returns the total number of requests processed since the server started.isRunning(): boolean: Checks if the server is currently listening for requests.
CopilotProxyConfig Interface
This interface defines the configuration options for the CopilotProxy.
export interface CopilotProxyConfig {
port: number;
host: string;
authToken?: string;
requireAuth?: boolean;
maxTokens: number;
maxTokensLimit?: number;
rateLimitPerMinute?: number;
onCompletion: (req: CopilotCompletionRequest) => Promise<CopilotCompletionResponse>;
}
Key Configuration Properties:
port,host: Standard network configuration for the HTTP server.authToken?: An optional bearer token string. If provided, requests must includeAuthorization: Bearer.requireAuth?: Iftrue, authentication is enforced even ifauthTokenis not set (useful for testing unauthorized access). Defaults tofalse.maxTokens: The defaultmax_tokensvalue to use if a client request does not specify it.maxTokensLimit?: An absolute upper bound formax_tokensrequested by clients. This prevents clients from requesting excessively long completions, defaulting to8192if not specified.rateLimitPerMinute?: The maximum number of requests allowed per minute per unique client IP address. Defaults to60.onCompletion: This is the most critical property. It's a callback function that the proxy invokes when a valid completion request is received. This function is responsible for interacting with the actual AI model and returning aCopilotCompletionResponse.
CopilotCompletionRequest & CopilotCompletionResponse Interfaces
These interfaces define the standardized structure for completion requests and responses, mirroring the expected format of the Copilot API.
CopilotCompletionRequest: Contains fields likeprompt,suffix,max_tokens,temperature,top_p,n,stop,language, andfile_path.CopilotCompletionResponse: Containsid, an array ofchoices(each withtext,index,finish_reason), and optionalusagestatistics.
How It Works
The CopilotProxy operates by creating a standard Node.js HTTP server and routing incoming requests through a series of checks and handlers.
sequenceDiagram
participant Client
participant CopilotProxy
participant CustomCompletionHandler
Client->>CopilotProxy: HTTP Request (e.g., POST /v1/completions)
CopilotProxy->>CopilotProxy: handleRequest(req, res)
CopilotProxy->>CopilotProxy: checkRateLimit(clientIp)
alt Rate Limit Exceeded
CopilotProxy-->>Client: 429 Rate Limit Exceeded
else
CopilotProxy->>CopilotProxy: authenticate(req)
alt Unauthorized
CopilotProxy-->>Client: 401 Unauthorized
else
alt GET /health
CopilotProxy-->>Client: 200 OK
alt GET /v1/models
CopilotProxy-->>Client: 200 OK (model list)
alt POST /v1/completions
CopilotProxy->>CopilotProxy: parseBody(req)
CopilotProxy->>CopilotProxy: Validate & Clamp max_tokens
CopilotProxy->>CustomCompletionHandler: config.onCompletion(request)
CustomCompletionHandler-->>CopilotProxy: CopilotCompletionResponse
CopilotProxy-->>Client: 200 OK (Completion Response)
else Other Path
CopilotProxy-->>Client: 404 Not Found
end
end
end
- Server Start: When
start()is called, anhttp.Serverinstance is created and begins listening on the configuredportandhost. All incoming requests are directed to thehandleRequestmethod. - Request Handling (
handleRequest):
- Rate Limiting: The
checkRateLimitmethod is called first. If the client's IP has exceeded therateLimitPerMinute, a429 Too Many Requestsresponse is sent. A background timer (rateLimitCleanupTimer) periodically cleans up stale IP entries from therateLimitMap. - Authentication: The
authenticatemethod verifies theAuthorizationheader. If authentication fails or is required but no token is present, a401 Unauthorizedresponse is sent. - Endpoint Routing:
GET /health: Returns a simple200 OKstatus.GET /v1/models: Returns a hardcoded JSON response listing a dummy model (id: 'codebuddy'). This is primarily for client compatibility.POST /v1/completions(or/v1/engines/codex/completions): This is the main completion endpoint.- The request body is parsed by
parseBody. - The parsed JSON is validated to ensure a
promptis present. - The
max_tokensvalue is set toconfig.maxTokensif not provided by the client, and then clamped toconfig.maxTokensLimitto prevent abuse. - The
config.onCompletioncallback is invoked with theCopilotCompletionRequest. - The response from
onCompletionis then sent back to the client with a200 OKstatus. - Any other path or method receives a
404 Not Foundresponse.
- Error Handling:
- Errors during body parsing (e.g., invalid JSON, payload too large) result in
400 Bad Request. - Errors originating from the
onCompletioncallback or other internal server issues are caught, and a500 Internal Server Erroris returned. The proxy ensures that internal error details are not leaked to the client.
Integration and Extensibility
The CopilotProxy is designed to be easily integrated into any Node.js application that needs to expose a Copilot-compatible API for custom AI models.
The primary point of integration and extensibility is the onCompletion callback in CopilotProxyConfig. This function is where you connect your custom AI logic.
Example Usage:
import { CopilotProxy, CopilotCompletionRequest, CopilotCompletionResponse } from 39;./copilot-proxy39;;
async function myCustomCompletionHandler(
request: CopilotCompletionRequest
): Promise<CopilotCompletionResponse> {
console.log(39;Received completion request:39;, request.prompt);
class="hl-cmt">// Simulate an AI model39;s response
const generatedText = `class="hl-cmt">// This is a simulated completion for: ${request.prompt}`;
return {
id: 39;simulated-completion-12339;,
choices: [{
text: generatedText,
index: 0,
finish_reason: 39;stop39;,
}],
usage: {
prompt_tokens: request.prompt.length, class="hl-cmt">// Simplified token count
completion_tokens: generatedText.length,
total_tokens: request.prompt.length + generatedText.length,
},
};
}
async function main() {
const proxy = new CopilotProxy({
port: 3000,
host: 39;127.0.0.139;,
authToken: 39;my-secret-token39;, class="hl-cmt">// Optional: set for authentication
maxTokens: 100,
maxTokensLimit: 500,
rateLimitPerMinute: 10,
onCompletion: myCustomCompletionHandler, class="hl-cmt">// Plug in your custom logic here
});
proxy.on(39;listening39;, () => {
console.log(`Copilot Proxy listening on http:class="hl-cmt">//${proxy.config.host}:${proxy.config.port}`);
console.log(39;Try: curl -H "Authorization: Bearer my-secret-token" -X POST -H "Content-Type: application/json" -d \39;{"prompt": "function helloWorld() {"}\39; http:class="hl-cmt">//127.0.0.1:3000/v1/completions39;);
});
proxy.on(39;error39;, (err) => {
console.error(39;Copilot Proxy error:39;, err);
});
await proxy.start();
class="hl-cmt">// To stop the proxy later:
class="hl-cmt">// await proxy.stop();
}
main().catch(console.error);
This module provides a flexible and robust foundation for building custom AI completion services that are compatible with existing Copilot-aware clients.