fix(openrouter): use /api endpoint root to prevent duplicated /v1 (#1728)

This commit is contained in:
Tam Nhu Tran committed 2026-09-09 15:38:22 -06:00
1 parent cb9eea1182
commit 375a3468b8
3 files changed
+44 -7

No files matched your search

+1 -1
View File
@@ -53,7 +53,7 @@ export interface ProviderPresetDefinition {
icon?: string;
}
export const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';
export const OPENROUTER_BASE_URL = 'https://openrouter.ai/api';
export const ORCAROUTER_BASE_URL = 'https://api.orcarouter.ai/v1';
/**
@@ -134,7 +134,7 @@ describe('profile-writer Anthropic direct', () => {
it('preserves OpenRouter ANTHROPIC_API_KEY blank behavior', () => {
const result = createApiProfile(
'openrouter-test',
'https://openrouter.ai/api/v1',
'https://openrouter.ai/api',
'sk-or-testkey',
{ default: 'anthropic/claude-opus-4.5', opus: 'anthropic/claude-opus-4.5', sonnet: 'anthropic/claude-opus-4.5', haiku: 'anthropic/claude-opus-4.5' }
);
@@ -145,7 +145,7 @@ describe('profile-writer Anthropic direct', () => {
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
// OpenRouter: proxy mode with ANTHROPIC_API_KEY explicitly blank
expect(settings.env.ANTHROPIC_BASE_URL).toBe('https://openrouter.ai/api/v1');
expect(settings.env.ANTHROPIC_BASE_URL).toBe('https://openrouter.ai/api');
expect(settings.env.ANTHROPIC_AUTH_TOKEN).toBe('sk-or-testkey');
expect(settings.env.ANTHROPIC_API_KEY).toBe('');
});
+41 -4
View File
@@ -1,6 +1,8 @@
import { existsSync } from 'fs';
import { resolve } from 'path';
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'fs';
import { tmpdir } from 'os';
import { join, resolve } from 'path';
import { describe, expect, it } from 'bun:test';
import { createApiProfile } from '../../../src/api/services/profile-writer';
import {
PROVIDER_PRESETS,
getPresetById,
@@ -113,9 +115,44 @@ describe('provider-presets', () => {
expect(isValidPresetId('te')).toBe(true);
});
it('uses OpenRouter v1 as the OpenAI-compatible API root', () => {
it('uses OpenRouter /api (without /v1) as the Anthropic-compatible API root to avoid double /v1 404 in Claude Code (#1728)', () => {
const preset = getPresetById('openrouter');
expect(preset?.baseUrl).toBe('https://openrouter.ai/api/v1');
expect(preset?.baseUrl).toBe('https://openrouter.ai/api');
const finalEndpoint = `${preset?.baseUrl}/v1/messages`;
expect(finalEndpoint).toBe('https://openrouter.ai/api/v1/messages');
expect(finalEndpoint).not.toContain('/v1/v1/');
});
it('generates an OpenRouter profile whose ANTHROPIC_BASE_URL does not duplicate /v1 (#1728)', () => {
const preset = getPresetById('openrouter');
expect(preset).toBeDefined();
const tempHome = mkdtempSync(join(tmpdir(), 'ccs-openrouter-tdd-'));
const prevCcsHome = process.env.CCS_HOME;
process.env.CCS_HOME = tempHome;
try {
const result = createApiProfile(
'openrouter-tdd',
preset!.baseUrl,
'sk-or-test-key',
{
default: preset!.defaultModel,
opus: preset!.defaultModel,
sonnet: preset!.defaultModel,
haiku: preset!.defaultModel,
}
);
expect(result.success).toBe(true);
const settings = JSON.parse(
readFileSync(join(tempHome, '.ccs', 'openrouter-tdd.settings.json'), 'utf8')
);
expect(settings.env.ANTHROPIC_BASE_URL).toBe('https://openrouter.ai/api');
expect(`${settings.env.ANTHROPIC_BASE_URL}/v1/messages`).toBe(
'https://openrouter.ai/api/v1/messages'
);
} finally {
process.env.CCS_HOME = prevCcsHome;
rmSync(tempHome, { recursive: true, force: true });
}
});
it('keeps Anthropic direct last in the recommended preset order and reuses the Claude logo', () => {