fix(cursor): migrate legacy settings and validate gitlab urls

This commit is contained in:
Tam Nhu Tran committed 2026-04-15 17:48:33 -04:00
1 parent 3b5941c60b
commit 58c2c46ed7
6 files changed
+209 -17

No files matched your search

@@ -318,6 +318,65 @@ describe('getEffectiveEnvVars local provider URL normalization', () => {
expect(repaired.env?.ANTHROPIC_DEFAULT_HAIKU_MODEL).toBeDefined();
});
it('imports legacy cursor settings into the dedicated provider path without reusing legacy transport auth', () => {
process.env.CCS_HOME = tempHome;
const legacySettingsPath = path.join(tempHome, '.ccs', 'cursor.settings.json');
const providerSettingsPath = path.join(
tempHome,
'.ccs',
'cliproxy',
'providers',
'cursor.settings.json'
);
fs.mkdirSync(path.dirname(legacySettingsPath), { recursive: true });
fs.writeFileSync(
legacySettingsPath,
JSON.stringify(
{
env: {
ANTHROPIC_BASE_URL: 'http://127.0.0.1:20129',
ANTHROPIC_AUTH_TOKEN: 'cursor-managed',
ANTHROPIC_API_KEY: 'legacy-cursor-api-key',
ANTHROPIC_MODEL: 'claude-4-sonnet',
ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-4-opus',
ANTHROPIC_DEFAULT_SONNET_MODEL: 'claude-4-sonnet',
ANTHROPIC_DEFAULT_HAIKU_MODEL: 'cursor-small',
ANTHROPIC_SMALL_FAST_MODEL: 'cursor-small',
DISABLE_TELEMETRY: '1',
},
hooks: {
PreToolUse: [{ matcher: 'Read', hooks: [] }],
},
},
null,
2
)
);
const env = getEffectiveEnvVars('cursor');
expect(env.ANTHROPIC_BASE_URL).toBe('http://127.0.0.1:8317/api/provider/cursor');
expect(env.ANTHROPIC_AUTH_TOKEN).toBe('ccs-internal-managed');
expect(env.ANTHROPIC_MODEL).toBe('claude-4-sonnet');
expect(env.ANTHROPIC_DEFAULT_OPUS_MODEL).toBe('claude-4-opus');
expect(env.ANTHROPIC_DEFAULT_HAIKU_MODEL).toBe('cursor-small');
expect(env.ANTHROPIC_SMALL_FAST_MODEL).toBe('cursor-small');
expect(env.DISABLE_TELEMETRY).toBe('1');
expect(env.ANTHROPIC_API_KEY).toBeUndefined();
const migrated = JSON.parse(fs.readFileSync(providerSettingsPath, 'utf-8')) as {
env: Record<string, string>;
hooks?: Record<string, unknown>;
};
expect(migrated.env.ANTHROPIC_BASE_URL).toBe('http://127.0.0.1:8317/api/provider/cursor');
expect(migrated.env.ANTHROPIC_AUTH_TOKEN).toBe('ccs-internal-managed');
expect(migrated.env.ANTHROPIC_MODEL).toBe('claude-4-sonnet');
expect(migrated.env.ANTHROPIC_DEFAULT_OPUS_MODEL).toBe('claude-4-opus');
expect(migrated.env.ANTHROPIC_SMALL_FAST_MODEL).toBe('cursor-small');
expect(migrated.env.ANTHROPIC_API_KEY).toBeUndefined();
expect(migrated.hooks?.PreToolUse).toBeDefined();
});
it('migrates deprecated agy sonnet 4.6 thinking IDs during ensureProviderSettings', () => {
process.env.CCS_HOME = tempHome;
const agySettingsPath = path.join(tempHome, '.ccs', 'agy.settings.json');
@@ -262,3 +262,37 @@ describe('promptGitLabPersonalAccessToken', () => {
expect(passwordSpy).toHaveBeenCalledWith('GitLab Personal Access Token');
});
});
describe('normalizeGitLabBaseUrl', () => {
it('returns undefined for blank values', async () => {
const { normalizeGitLabBaseUrl } = await import(
`../../../src/cliproxy/auth/oauth-handler?gitlab-url-empty=${Date.now()}`
);
expect(normalizeGitLabBaseUrl(undefined)).toBeUndefined();
expect(normalizeGitLabBaseUrl(' ')).toBeUndefined();
});
it('normalizes whitespace and trailing slashes for self-hosted URLs', async () => {
const { normalizeGitLabBaseUrl } = await import(
`../../../src/cliproxy/auth/oauth-handler?gitlab-url-normalize=${Date.now()}`
);
expect(normalizeGitLabBaseUrl(' https://gitlab.example.com/custom/ ')).toBe(
'https://gitlab.example.com/custom'
);
});
it('rejects malformed or scheme-less URLs before hitting CLIProxy', async () => {
const { normalizeGitLabBaseUrl } = await import(
`../../../src/cliproxy/auth/oauth-handler?gitlab-url-invalid=${Date.now()}`
);
expect(() => normalizeGitLabBaseUrl('gitlab.example.com')).toThrow(
'GitLab URL must be a valid http:// or https:// URL'
);
expect(() => normalizeGitLabBaseUrl('ftp://gitlab.example.com')).toThrow(
'GitLab URL must use http:// or https://'
);
});
});