From 13079cdab4cf08fc48c8fe7487a2852c46c579e2 Mon Sep 17 00:00:00 2001 From: Rohan Mukherjee Date: Fri, 30 Jan 2026 17:45:18 +0530 Subject: [PATCH] fix: truncate trailing slashes in AIG base URL --- src/gateway/env.test.ts | 35 +++++++++++++++++++++++++++++++++++ src/gateway/env.ts | 12 +++++++----- start-moltbot.sh | 2 +- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/gateway/env.test.ts b/src/gateway/env.test.ts index 3594e18..29f033d 100644 --- a/src/gateway/env.test.ts +++ b/src/gateway/env.test.ts @@ -135,4 +135,39 @@ describe('buildEnvVars', () => { TELEGRAM_BOT_TOKEN: 'tg', }); }); + + it('handles trailing slash in AI_GATEWAY_BASE_URL for OpenAI', () => { + const env = createMockEnv({ + AI_GATEWAY_API_KEY: 'sk-gateway-key', + AI_GATEWAY_BASE_URL: 'https://gateway.ai.cloudflare.com/v1/123/my-gw/openai/', + }); + const result = buildEnvVars(env); + expect(result.OPENAI_API_KEY).toBe('sk-gateway-key'); + expect(result.OPENAI_BASE_URL).toBe('https://gateway.ai.cloudflare.com/v1/123/my-gw/openai'); + expect(result.AI_GATEWAY_BASE_URL).toBe('https://gateway.ai.cloudflare.com/v1/123/my-gw/openai'); + expect(result.ANTHROPIC_API_KEY).toBeUndefined(); + }); + + it('handles trailing slash in AI_GATEWAY_BASE_URL for Anthropic', () => { + const env = createMockEnv({ + AI_GATEWAY_API_KEY: 'sk-gateway-key', + AI_GATEWAY_BASE_URL: 'https://gateway.ai.cloudflare.com/v1/123/my-gw/anthropic/', + }); + const result = buildEnvVars(env); + expect(result.ANTHROPIC_API_KEY).toBe('sk-gateway-key'); + expect(result.ANTHROPIC_BASE_URL).toBe('https://gateway.ai.cloudflare.com/v1/123/my-gw/anthropic'); + expect(result.AI_GATEWAY_BASE_URL).toBe('https://gateway.ai.cloudflare.com/v1/123/my-gw/anthropic'); + expect(result.OPENAI_API_KEY).toBeUndefined(); + }); + + it('handles multiple trailing slashes in AI_GATEWAY_BASE_URL', () => { + const env = createMockEnv({ + AI_GATEWAY_API_KEY: 'sk-gateway-key', + AI_GATEWAY_BASE_URL: 'https://gateway.ai.cloudflare.com/v1/123/my-gw/openai///', + }); + const result = buildEnvVars(env); + expect(result.OPENAI_API_KEY).toBe('sk-gateway-key'); + expect(result.OPENAI_BASE_URL).toBe('https://gateway.ai.cloudflare.com/v1/123/my-gw/openai'); + expect(result.AI_GATEWAY_BASE_URL).toBe('https://gateway.ai.cloudflare.com/v1/123/my-gw/openai'); + }); }); diff --git a/src/gateway/env.ts b/src/gateway/env.ts index 26f1887..a57e781 100644 --- a/src/gateway/env.ts +++ b/src/gateway/env.ts @@ -9,7 +9,9 @@ import type { MoltbotEnv } from '../types'; export function buildEnvVars(env: MoltbotEnv): Record { const envVars: Record = {}; - const isOpenAIGateway = env.AI_GATEWAY_BASE_URL?.endsWith('/openai'); + // Normalize the base URL by removing trailing slashes + const normalizedBaseUrl = env.AI_GATEWAY_BASE_URL?.replace(/\/+$/, ''); + const isOpenAIGateway = normalizedBaseUrl?.endsWith('/openai'); // AI Gateway vars take precedence // Map to the appropriate provider env var based on the gateway endpoint @@ -30,13 +32,13 @@ export function buildEnvVars(env: MoltbotEnv): Record { } // Pass base URL (used by start-moltbot.sh to determine provider) - if (env.AI_GATEWAY_BASE_URL) { - envVars.AI_GATEWAY_BASE_URL = env.AI_GATEWAY_BASE_URL; + if (normalizedBaseUrl) { + envVars.AI_GATEWAY_BASE_URL = normalizedBaseUrl; // Also set the provider-specific base URL env var if (isOpenAIGateway) { - envVars.OPENAI_BASE_URL = env.AI_GATEWAY_BASE_URL; + envVars.OPENAI_BASE_URL = normalizedBaseUrl; } else { - envVars.ANTHROPIC_BASE_URL = env.AI_GATEWAY_BASE_URL; + envVars.ANTHROPIC_BASE_URL = normalizedBaseUrl; } } else if (env.ANTHROPIC_BASE_URL) { envVars.ANTHROPIC_BASE_URL = env.ANTHROPIC_BASE_URL; diff --git a/start-moltbot.sh b/start-moltbot.sh index 977ebf3..7e225e8 100644 --- a/start-moltbot.sh +++ b/start-moltbot.sh @@ -212,7 +212,7 @@ if (process.env.SLACK_BOT_TOKEN && process.env.SLACK_APP_TOKEN) { // Usage: Set AI_GATEWAY_BASE_URL or ANTHROPIC_BASE_URL to your endpoint like: // https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/anthropic // https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai -const baseUrl = process.env.AI_GATEWAY_BASE_URL || process.env.ANTHROPIC_BASE_URL || ''; +const baseUrl = (process.env.AI_GATEWAY_BASE_URL || process.env.ANTHROPIC_BASE_URL || '').replace(/\/+$/, ''); const isOpenAI = baseUrl.endsWith('/openai'); if (isOpenAI) {