mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-14 12:16:38 +00:00
Merge pull request #1575 from walker1211/codex/fix-cliproxy-provider-routes
Fix CLIProxy provider routes for original backend
This commit is contained in:
14 files changed
+451
-107
No files matched your search
@@ -8,6 +8,8 @@ import {
|
||||
resolveCliproxyBridgeProfile,
|
||||
suggestCliproxyBridgeName,
|
||||
} from '../../../src/api/services/cliproxy-profile-bridge';
|
||||
import { invalidateConfigCache } from '../../../src/config/config-loader-facade';
|
||||
import { clearConfigCache } from '../../../src/cliproxy/config/base-config-loader';
|
||||
|
||||
describe('cliproxy-profile-bridge', () => {
|
||||
let tempHome = '';
|
||||
@@ -17,6 +19,8 @@ describe('cliproxy-profile-bridge', () => {
|
||||
tempHome = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-cliproxy-bridge-'));
|
||||
originalCcsHome = process.env.CCS_HOME;
|
||||
process.env.CCS_HOME = tempHome;
|
||||
invalidateConfigCache();
|
||||
clearConfigCache();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -25,18 +29,32 @@ describe('cliproxy-profile-bridge', () => {
|
||||
} else {
|
||||
process.env.CCS_HOME = originalCcsHome;
|
||||
}
|
||||
invalidateConfigCache();
|
||||
clearConfigCache();
|
||||
|
||||
if (tempHome && fs.existsSync(tempHome)) {
|
||||
fs.rmSync(tempHome, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('resolves routed profile payload for a local CLIProxy provider', () => {
|
||||
function writeBackendConfig(backend: 'original' | 'plus'): void {
|
||||
const ccsDir = path.join(tempHome, '.ccs');
|
||||
fs.mkdirSync(ccsDir, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(ccsDir, 'config.yaml'),
|
||||
['version: 1', 'cliproxy:', ` backend: ${backend}`, ''].join('\n'),
|
||||
'utf8'
|
||||
);
|
||||
invalidateConfigCache();
|
||||
clearConfigCache();
|
||||
}
|
||||
|
||||
it('resolves routed profile payload for a local original-backend CLIProxy provider', () => {
|
||||
const bridge = resolveCliproxyBridgeProfile('gemini');
|
||||
|
||||
expect(bridge.name).toBe('gemini-api');
|
||||
expect(bridge.baseUrl).toBe('http://127.0.0.1:8317/api/provider/gemini');
|
||||
expect(bridge.routePath).toBe('/api/provider/gemini');
|
||||
expect(bridge.baseUrl).toBe('http://127.0.0.1:8317/');
|
||||
expect(bridge.routePath).toBe('/');
|
||||
expect(bridge.models.default.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
@@ -49,6 +67,7 @@ describe('cliproxy-profile-bridge', () => {
|
||||
});
|
||||
|
||||
it('detects CLIProxy-backed profile metadata and normalizes localhost loopback URLs', () => {
|
||||
writeBackendConfig('plus');
|
||||
const metadata = resolveCliproxyBridgeMetadata({
|
||||
env: {
|
||||
ANTHROPIC_BASE_URL: 'http://localhost:8317/api/provider/gemini',
|
||||
|
||||
@@ -6,24 +6,61 @@ import {
|
||||
buildCodexCliproxyProviderBaseUrl,
|
||||
ensureCodexCliproxyProviderConfig,
|
||||
} from '../../../src/targets/codex-cliproxy-provider-config';
|
||||
import { invalidateConfigCache } from '../../../src/config/config-loader-facade';
|
||||
import { clearConfigCache } from '../../../src/cliproxy/config/base-config-loader';
|
||||
|
||||
describe('codex cliproxy provider config repair', () => {
|
||||
let tempHome: string;
|
||||
let codexHome: string;
|
||||
let configPath: string;
|
||||
let env: NodeJS.ProcessEnv;
|
||||
let originalCcsHome: string | undefined;
|
||||
|
||||
beforeEach(() => {
|
||||
originalCcsHome = process.env.CCS_HOME;
|
||||
tempHome = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-codex-provider-config-'));
|
||||
codexHome = path.join(tempHome, '.codex');
|
||||
configPath = path.join(codexHome, 'config.toml');
|
||||
env = { CODEX_HOME: codexHome } as NodeJS.ProcessEnv;
|
||||
process.env.CCS_HOME = tempHome;
|
||||
invalidateConfigCache();
|
||||
clearConfigCache();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (originalCcsHome !== undefined) {
|
||||
process.env.CCS_HOME = originalCcsHome;
|
||||
} else {
|
||||
delete process.env.CCS_HOME;
|
||||
}
|
||||
invalidateConfigCache();
|
||||
clearConfigCache();
|
||||
fs.rmSync(tempHome, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
function writeBackendConfig(backend: 'original' | 'plus'): void {
|
||||
const ccsDir = path.join(tempHome, '.ccs');
|
||||
fs.mkdirSync(ccsDir, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(ccsDir, 'config.yaml'),
|
||||
['version: 1', 'cliproxy:', ` backend: ${backend}`, ''].join('\n'),
|
||||
'utf8'
|
||||
);
|
||||
invalidateConfigCache();
|
||||
clearConfigCache();
|
||||
}
|
||||
|
||||
it('uses the original backend root URL by default', () => {
|
||||
expect(buildCodexCliproxyProviderBaseUrl(8317)).toBe('http://127.0.0.1:8317');
|
||||
});
|
||||
|
||||
it('uses the plus backend scoped Codex URL when configured', () => {
|
||||
writeBackendConfig('plus');
|
||||
expect(buildCodexCliproxyProviderBaseUrl(8317)).toBe(
|
||||
'http://127.0.0.1:8317/api/provider/codex'
|
||||
);
|
||||
});
|
||||
|
||||
it('creates the cliproxy model provider when config.toml is missing', async () => {
|
||||
const result = await ensureCodexCliproxyProviderConfig(8317, env);
|
||||
|
||||
@@ -32,6 +69,7 @@ describe('codex cliproxy provider config repair', () => {
|
||||
const rawText = fs.readFileSync(configPath, 'utf8');
|
||||
expect(rawText).toContain('[model_providers.cliproxy]');
|
||||
expect(rawText).toContain('name = "CLIProxy Codex"');
|
||||
expect(rawText).toContain('base_url = "http://127.0.0.1:8317"');
|
||||
expect(rawText).toContain('env_key = "CLIPROXY_API_KEY"');
|
||||
expect(rawText).not.toContain('model_provider = "cliproxy"');
|
||||
});
|
||||
@@ -78,7 +116,7 @@ wire_api = "responses"
|
||||
expect(result.changed).toBe(true);
|
||||
expect(result.envKey).toBe('CLIPROXY_API_KEY');
|
||||
const rawText = fs.readFileSync(configPath, 'utf8');
|
||||
expect(rawText).toContain('base_url = "http://localhost:8317/api/provider/codex"');
|
||||
expect(rawText).toContain('base_url = "http://127.0.0.1:9321"');
|
||||
expect(rawText).toContain('env_key = "CLIPROXY_API_KEY"');
|
||||
expect(rawText).toContain('requires_openai_auth = false');
|
||||
expect(rawText).toContain('supports_websockets = false');
|
||||
@@ -142,7 +180,29 @@ supports_websockets = false
|
||||
expect(fs.readFileSync(configPath, 'utf8')).toBe(rawText);
|
||||
});
|
||||
|
||||
it('leaves a ready localhost provider unchanged', async () => {
|
||||
it('repairs a stale ready localhost provider to the original backend root URL', async () => {
|
||||
fs.mkdirSync(codexHome, { recursive: true });
|
||||
const rawText = `[model_providers.cliproxy]
|
||||
name = "CLIProxy Codex"
|
||||
base_url = "http://localhost:8317/api/provider/codex"
|
||||
env_key = "CLIPROXY_API_KEY"
|
||||
wire_api = "responses"
|
||||
requires_openai_auth = false
|
||||
supports_websockets = false
|
||||
`;
|
||||
fs.writeFileSync(configPath, rawText, 'utf8');
|
||||
|
||||
const result = await ensureCodexCliproxyProviderConfig(8317, env);
|
||||
|
||||
expect(result.changed).toBe(true);
|
||||
expect(result.envKey).toBe('CLIPROXY_API_KEY');
|
||||
const repairedText = fs.readFileSync(configPath, 'utf8');
|
||||
expect(repairedText).toContain('base_url = "http://127.0.0.1:8317"');
|
||||
expect(repairedText).not.toContain('/api/provider/codex');
|
||||
});
|
||||
|
||||
it('leaves a ready plus-backend localhost provider unchanged', async () => {
|
||||
writeBackendConfig('plus');
|
||||
fs.mkdirSync(codexHome, { recursive: true });
|
||||
const rawText = `[model_providers.cliproxy]
|
||||
name = "CLIProxy Codex"
|
||||
@@ -188,7 +248,7 @@ supports_websockets = false
|
||||
|
||||
[model_providers.cliproxy]
|
||||
name = "CLIProxy Codex"
|
||||
base_url = "http://localhost:8317/api/provider/codex"
|
||||
base_url = "http://127.0.0.1:8317"
|
||||
env_key = "CLIPROXY_API_KEY"
|
||||
wire_api = "responses"
|
||||
requires_openai_auth = false
|
||||
@@ -239,7 +299,7 @@ supports_websockets = false
|
||||
|
||||
[model_providers.cliproxy]
|
||||
name = "CLIProxy Codex"
|
||||
base_url = "http://localhost:8317/api/provider/codex"
|
||||
base_url = "http://127.0.0.1:8317"
|
||||
env_key = "CLIPROXY_API_KEY"
|
||||
wire_api = "responses"
|
||||
requires_openai_auth = false
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { afterEach, describe, expect, it } from 'bun:test';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
|
||||
import { mkdtempSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import type { UnifiedConfig } from '../../../../src/config/unified-config-types';
|
||||
import { runBrowserSetup, type BrowserSetupDeps } from '../../../../src/utils/browser/browser-setup';
|
||||
import {
|
||||
runBrowserSetup,
|
||||
type BrowserSetupDeps,
|
||||
} from '../../../../src/utils/browser/browser-setup';
|
||||
|
||||
function createUnifiedConfig(userDataDir: string): UnifiedConfig {
|
||||
return {
|
||||
@@ -96,8 +99,36 @@ function createUnifiedConfig(userDataDir: string): UnifiedConfig {
|
||||
|
||||
describe('browser setup', () => {
|
||||
let tempDir = '';
|
||||
let originalBrowserUserDataDir: string | undefined;
|
||||
let originalBrowserProfileDir: string | undefined;
|
||||
let originalBrowserDevtoolsPort: string | undefined;
|
||||
|
||||
beforeEach(() => {
|
||||
originalBrowserUserDataDir = process.env.CCS_BROWSER_USER_DATA_DIR;
|
||||
originalBrowserProfileDir = process.env.CCS_BROWSER_PROFILE_DIR;
|
||||
originalBrowserDevtoolsPort = process.env.CCS_BROWSER_DEVTOOLS_PORT;
|
||||
delete process.env.CCS_BROWSER_USER_DATA_DIR;
|
||||
delete process.env.CCS_BROWSER_PROFILE_DIR;
|
||||
delete process.env.CCS_BROWSER_DEVTOOLS_PORT;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (originalBrowserUserDataDir !== undefined) {
|
||||
process.env.CCS_BROWSER_USER_DATA_DIR = originalBrowserUserDataDir;
|
||||
} else {
|
||||
delete process.env.CCS_BROWSER_USER_DATA_DIR;
|
||||
}
|
||||
if (originalBrowserProfileDir !== undefined) {
|
||||
process.env.CCS_BROWSER_PROFILE_DIR = originalBrowserProfileDir;
|
||||
} else {
|
||||
delete process.env.CCS_BROWSER_PROFILE_DIR;
|
||||
}
|
||||
if (originalBrowserDevtoolsPort !== undefined) {
|
||||
process.env.CCS_BROWSER_DEVTOOLS_PORT = originalBrowserDevtoolsPort;
|
||||
} else {
|
||||
delete process.env.CCS_BROWSER_DEVTOOLS_PORT;
|
||||
}
|
||||
|
||||
if (tempDir) {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
tempDir = '';
|
||||
|
||||
@@ -5,6 +5,8 @@ import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import type { Server } from 'http';
|
||||
import profileRoutes from '../../../src/web-server/routes/profile-routes';
|
||||
import { invalidateConfigCache } from '../../../src/config/config-loader-facade';
|
||||
import { clearConfigCache } from '../../../src/cliproxy/config/base-config-loader';
|
||||
|
||||
describe('profile-routes cliproxy bridge', () => {
|
||||
let server: Server;
|
||||
@@ -42,6 +44,8 @@ describe('profile-routes cliproxy bridge', () => {
|
||||
tempHome = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-profile-routes-cliproxy-bridge-'));
|
||||
originalCcsHome = process.env.CCS_HOME;
|
||||
process.env.CCS_HOME = tempHome;
|
||||
invalidateConfigCache();
|
||||
clearConfigCache();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -50,6 +54,8 @@ describe('profile-routes cliproxy bridge', () => {
|
||||
} else {
|
||||
delete process.env.CCS_HOME;
|
||||
}
|
||||
invalidateConfigCache();
|
||||
clearConfigCache();
|
||||
|
||||
if (tempHome && fs.existsSync(tempHome)) {
|
||||
fs.rmSync(tempHome, { recursive: true, force: true });
|
||||
|
||||
Reference in new issue
Block a user