This guide provides coding standards and workflows for AI agents working in this repository.
ghcp-ollama is a GitHub Copilot proxy providing Ollama, OpenAI, and Anthropic compatible APIs.
- Language: JavaScript (ES Modules)
- Runtime: Node.js >=18.0.0
- Package Manager: npm
- Module System: ESM (
"type": "module"in package.json)
npm install # Install dependencies
npm start # Start server (production)
npm run dev # Start server with auto-reload (development)
npm run build # Build the projectnpm run lint # Check code style
npm run lint:fix # Auto-fix code style issues# Run all tests (unit + integration)
npm test
# Run unit tests only (fast, no server required)
npm run test:unit
# Run integration tests (requires running server)
npm run test:integration
# Run a single test file
npx vitest run tests/unit/image_utils.test.js
# Run tests matching a pattern
npx vitest run tests/unit/adapters/
# Watch mode for test-driven development
npm run test:watch
# Interactive UI for tests
npm run test:ui
# Coverage report
npm run test:coverage
# Generate golden outputs for integration tests
npm run test:goldennpm run server:start # Start server as daemon
npm run server:stop # Stop server daemon
npm run server:restart # Restart server daemon
npm run server:status # Check server status- Indentation: 2 spaces
- Quotes: Double quotes (
") - Semicolons: Required (
;) - Line endings: Unix (LF)
- Trailing commas: Only in multiline
- Console:
console.log()allowed (not an error) - Unused vars: Error (except params prefixed with
_)
// External modules first
import fs from "fs";
import path from "path";
import express from "express";
// Internal modules second
import { CopilotAuth } from "./utils/auth_client.js";
import { detectImageType } from "./utils/image_utils.js";
// Always use .js extension in imports (ESM requirement)src/
├── utils/
│ ├── adapters/ # API format converters
│ │ ├── base_adapter.js
│ │ ├── ollama_adapter.js
│ │ ├── openai_adapter.js
│ │ └── anthropic_adapter.js
│ ├── auth_client.js # GitHub authentication
│ ├── chat_client.js # Chat API client
│ └── image_utils.js # Image processing
└── server.js # Main server
- Files:
snake_case.js(e.g.,chat_client.js,base_adapter.js) - Classes:
PascalCase(e.g.,BaseAdapter,OllamaAdapter) - Functions:
camelCase(e.g.,convertRequest,parseResponse) - Constants:
UPPER_SNAKE_CASE(e.g.,BASE_URL,TIMEOUT) - Private params: Prefix with
_(e.g.,_payload,_response)
/**
* Brief description of function/class.
* Additional details if needed.
*
* @param {string} base64String - Parameter description
* @param {Object} options - Options object
* @param {boolean} [options.stream=false] - Optional parameter
* @returns {string} Return value description
* @throws {Error} When something goes wrong
*/
export function detectImageType(base64String) {
// Implementation
}// Always validate inputs
if (!payload || typeof payload !== "object") {
throw new Error("Invalid payload");
}
// Provide descriptive error messages
throw new Error("BaseAdapter is an abstract class and cannot be instantiated directly");
// Use try-catch for async operations
try {
const result = await apiCall();
return { success: true, data: result };
} catch (error) {
return { success: false, error: error.message };
}Unit Tests (tests/unit/)
- No external dependencies (server, network)
- Use mocks for external services
- Test file naming:
<module>.test.js - Structure:
describe>itpattern - Use fixtures from
tests/unit/fixtures/
Integration Tests (tests/integration/)
- Require running server
- Test real API endpoints
- Use golden outputs for comparison
- Timeout: 30 seconds per test
Test Structure
import { describe, it, expect } from "vitest";
describe("ModuleName", () => {
describe("functionName", () => {
it("should do something specific", () => {
const result = functionName(input);
expect(result).toBe(expected);
});
});
});- All comments MUST be in English (not Chinese)
- Never commit secrets (use .env, don't commit .env files)
- Always use ESM imports (not
require()) - Test before committing (
npm run lint && npm run test:unit) - Deep clone fixtures in tests to avoid mutation between tests
- Coverage target: 80%+ for adapters, 90%+ for utilities
- Extend
BaseAdapterclass - Implement
convertRequest(),parseResponse(),parseStreamChunk() - Add unit tests in
tests/unit/adapters/ - Add integration tests in
tests/integration/ - Update
chat_client.jsto use new adapter
- Write a failing test that reproduces the bug
- Fix the bug in source code
- Verify test passes:
npx vitest run path/to/test.js - Run full suite:
npm run test:unit
- Write unit tests first (TDD approach)
- Implement feature
- Add integration tests if needed
- Update README.md if user-facing
- Ensure coverage remains above threshold