From f9f3a245689cdfe04f2fbb295c3b62a91833d852 Mon Sep 17 00:00:00 2001 From: Thomas Mulder Date: Tue, 22 Apr 2025 14:13:20 +0200 Subject: [PATCH] add test + documentation --- README.md | 1 + docs/configuration.md | 2 ++ tests/unit/ai-client-utils.test.js | 53 ++++++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7459bc05..e542feeb 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ MCP (Model Control Protocol) provides the easiest way to get started with Task M "args": ["-y", "task-master-ai"], "env": { "ANTHROPIC_API_KEY": "YOUR_ANTHROPIC_API_KEY_HERE", + "ANTHROPIC_API_BASE_URL": "YOUR_CUSTOM_BASE_URL_HERE (optional)", "PERPLEXITY_API_KEY": "YOUR_PERPLEXITY_API_KEY_HERE", "MODEL": "claude-3-7-sonnet-20250219", "PERPLEXITY_MODEL": "sonar-pro", diff --git a/docs/configuration.md b/docs/configuration.md index 70b86c05..d203e920 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -8,6 +8,7 @@ Task Master can be configured through environment variables in a `.env` file at ## Optional Configuration +- `ANTHROPIC_API_BASE_URL`: Optional custom base URL for Anthropic API (Example: `ANTHROPIC_API_BASE_URL=https://gcp-vertex.mydomain.com`) - `MODEL` (Default: `"claude-3-7-sonnet-20250219"`): Claude model to use (Example: `MODEL=claude-3-opus-20240229`) - `MAX_TOKENS` (Default: `"4000"`): Maximum tokens for responses (Example: `MAX_TOKENS=8000`) - `TEMPERATURE` (Default: `"0.7"`): Temperature for model responses (Example: `TEMPERATURE=0.5`) @@ -27,6 +28,7 @@ Task Master can be configured through environment variables in a `.env` file at ANTHROPIC_API_KEY=sk-ant-api03-your-api-key # Optional - Claude Configuration +ANTHROPIC_API_BASE_URL=https://gcp-vertex.mydomain.com MODEL=claude-3-7-sonnet-20250219 MAX_TOKENS=4000 TEMPERATURE=0.7 diff --git a/tests/unit/ai-client-utils.test.js b/tests/unit/ai-client-utils.test.js index b1c8ae06..b20fd174 100644 --- a/tests/unit/ai-client-utils.test.js +++ b/tests/unit/ai-client-utils.test.js @@ -57,8 +57,32 @@ describe('AI Client Utilities', () => { }); describe('getAnthropicClientForMCP', () => { - it('should initialize client with API key from session', () => { + it('should initialize client with API key and base URL from session', () => { // Setup + const session = { + env: { + ANTHROPIC_API_KEY: 'test-key-from-session', + ANTHROPIC_API_BASE_URL: 'https://custom-api.example.com' + } + }; + const mockLog = { error: jest.fn() }; + + // Execute + const client = getAnthropicClientForMCP(session, mockLog); + + // Verify + expect(client).toBeDefined(); + expect(client.messages.create).toBeDefined(); + expect(mockLog.error).not.toHaveBeenCalled(); + expect(Anthropic).toHaveBeenCalledWith(expect.objectContaining({ + apiKey: 'test-key-from-session', + baseURL: 'https://custom-api.example.com' + })); + }); + + it('should initialize client with base URL from process.env when session URL is missing', () => { + // Setup + process.env.ANTHROPIC_API_BASE_URL = 'https://env-api.example.com'; const session = { env: { ANTHROPIC_API_KEY: 'test-key-from-session' @@ -71,8 +95,31 @@ describe('AI Client Utilities', () => { // Verify expect(client).toBeDefined(); - expect(client.messages.create).toBeDefined(); - expect(mockLog.error).not.toHaveBeenCalled(); + expect(Anthropic).toHaveBeenCalledWith(expect.objectContaining({ + apiKey: 'test-key-from-session', + baseURL: 'https://env-api.example.com' + })); + }); + + it('should initialize client without base URL when not provided', () => { + // Setup + delete process.env.ANTHROPIC_API_BASE_URL; + const session = { + env: { + ANTHROPIC_API_KEY: 'test-key-from-session' + } + }; + const mockLog = { error: jest.fn() }; + + // Execute + const client = getAnthropicClientForMCP(session, mockLog); + + // Verify + expect(client).toBeDefined(); + expect(Anthropic).toHaveBeenCalledWith(expect.objectContaining({ + apiKey: 'test-key-from-session', + baseURL: undefined + })); }); it('should fall back to process.env when session key is missing', () => {