mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
feat: add URL trailing slash compatibility for system prompt mappings
- Add normalizeUrl() function to standardize URLs by removing trailing slashes - Add urlMatches() function to compare URLs ignoring trailing slash differences - Replace direct includes() comparison with urlMatches() for baseUrl matching - Add comprehensive tests to verify URL matching with/without trailing slashes - Fixes issue where URLs like 'https://api.example.com' and 'https://api.example.com/' were treated as different
This commit is contained in:
@@ -106,3 +106,96 @@ describe('Core System Prompt (prompts.ts)', () => {
|
||||
expect(prompt).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('URL matching with trailing slash compatibility', () => {
|
||||
it('should match URLs with and without trailing slash', () => {
|
||||
const config = {
|
||||
systemPromptMappings: [
|
||||
{
|
||||
baseUrls: ['https://api.example.com'],
|
||||
modelNames: ['gpt-4'],
|
||||
template: 'Custom template for example.com',
|
||||
},
|
||||
{
|
||||
baseUrls: ['https://api.openai.com/'],
|
||||
modelNames: ['gpt-3.5-turbo'],
|
||||
template: 'Custom template for openai.com',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Simulate environment variables
|
||||
const originalEnv = process.env;
|
||||
|
||||
// Test case 1: No trailing slash in config, actual URL has trailing slash
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
OPENAI_BASE_URL: 'https://api.example.com/',
|
||||
OPENAI_MODEL: 'gpt-4',
|
||||
};
|
||||
|
||||
const result1 = getCoreSystemPrompt(undefined, config);
|
||||
expect(result1).toContain('Custom template for example.com');
|
||||
|
||||
// Test case 2: Config has trailing slash, actual URL has no trailing slash
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
OPENAI_BASE_URL: 'https://api.openai.com',
|
||||
OPENAI_MODEL: 'gpt-3.5-turbo',
|
||||
};
|
||||
|
||||
const result2 = getCoreSystemPrompt(undefined, config);
|
||||
expect(result2).toContain('Custom template for openai.com');
|
||||
|
||||
// Test case 3: No trailing slash in config, actual URL has no trailing slash
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
OPENAI_BASE_URL: 'https://api.example.com',
|
||||
OPENAI_MODEL: 'gpt-4',
|
||||
};
|
||||
|
||||
const result3 = getCoreSystemPrompt(undefined, config);
|
||||
expect(result3).toContain('Custom template for example.com');
|
||||
|
||||
// Test case 4: Config has trailing slash, actual URL has trailing slash
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
OPENAI_BASE_URL: 'https://api.openai.com/',
|
||||
OPENAI_MODEL: 'gpt-3.5-turbo',
|
||||
};
|
||||
|
||||
const result4 = getCoreSystemPrompt(undefined, config);
|
||||
expect(result4).toContain('Custom template for openai.com');
|
||||
|
||||
// Restore original environment variables
|
||||
process.env = originalEnv;
|
||||
});
|
||||
|
||||
it('should not match when URLs are different', () => {
|
||||
const config = {
|
||||
systemPromptMappings: [
|
||||
{
|
||||
baseUrls: ['https://api.example.com'],
|
||||
modelNames: ['gpt-4'],
|
||||
template: 'Custom template for example.com',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const originalEnv = process.env;
|
||||
|
||||
// Test case: URLs do not match
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
OPENAI_BASE_URL: 'https://api.different.com',
|
||||
OPENAI_MODEL: 'gpt-4',
|
||||
};
|
||||
|
||||
const result = getCoreSystemPrompt(undefined, config);
|
||||
// Should return default template, not contain custom template
|
||||
expect(result).not.toContain('Custom template for example.com');
|
||||
|
||||
// Restore original environment variables
|
||||
process.env = originalEnv;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,6 +28,21 @@ export interface SystemPromptConfig {
|
||||
systemPromptMappings?: ModelTemplateMapping[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a URL by removing trailing slash for consistent comparison
|
||||
*/
|
||||
function normalizeUrl(url: string): string {
|
||||
return url.endsWith('/') ? url.slice(0, -1) : url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a URL matches any URL in the array, ignoring trailing slashes
|
||||
*/
|
||||
function urlMatches(urlArray: string[], targetUrl: string): boolean {
|
||||
const normalizedTarget = normalizeUrl(targetUrl);
|
||||
return urlArray.some((url) => normalizeUrl(url) === normalizedTarget);
|
||||
}
|
||||
|
||||
export function getCoreSystemPrompt(
|
||||
userMemory?: string,
|
||||
config?: SystemPromptConfig,
|
||||
@@ -59,13 +74,13 @@ export function getCoreSystemPrompt(
|
||||
if (
|
||||
baseUrls &&
|
||||
modelNames &&
|
||||
baseUrls.includes(currentBaseUrl) &&
|
||||
urlMatches(baseUrls, currentBaseUrl) &&
|
||||
modelNames.includes(currentModel)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseUrls && baseUrls.includes(currentBaseUrl) && !modelNames) {
|
||||
if (baseUrls && urlMatches(baseUrls, currentBaseUrl) && !modelNames) {
|
||||
return true;
|
||||
}
|
||||
if (modelNames && modelNames.includes(currentModel) && !baseUrls) {
|
||||
|
||||
Reference in New Issue
Block a user