mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 08:17:11 +00:00
feat(cliproxy): add Qoder as a CLIProxy provider channel
Add Qoder AI coding assistant as a supported CLIProxy provider: - Device code OAuth flow with --qoder-login flag - Plus-only backend (CLIProxyAPIPlus required) - No built-in token refresh (unsupported, like Kilo) - Auth URL: https://qoder.com/device/selectAccounts - Auth file prefix: qoder- - Token type: qoder
This commit is contained in:
@@ -306,6 +306,13 @@ export const OAUTH_CONFIGS: Record<CLIProxyProvider, ProviderOAuthConfig> = {
|
||||
scopes: [],
|
||||
authFlag: '--kilo-login',
|
||||
},
|
||||
qoder: {
|
||||
provider: 'qoder',
|
||||
displayName: 'Qoder',
|
||||
authUrl: 'https://qoder.com/device/selectAccounts',
|
||||
scopes: [],
|
||||
authFlag: '--qoder-login',
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -182,6 +182,18 @@ export const PROVIDER_CAPABILITIES: Record<CLIProxyProvider, ProviderCapabilitie
|
||||
tokenTypeValues: ['kilo'],
|
||||
aliases: [],
|
||||
},
|
||||
qoder: {
|
||||
displayName: 'Qoder',
|
||||
description: 'Qoder AI coding assistant',
|
||||
oauthFlow: 'device_code',
|
||||
callbackPort: null,
|
||||
callbackProviderName: 'qoder',
|
||||
authUrlProviderName: 'qoder',
|
||||
refreshOwnership: 'unsupported',
|
||||
authFilePrefixes: ['qoder-'],
|
||||
tokenTypeValues: ['qoder'],
|
||||
aliases: [],
|
||||
},
|
||||
};
|
||||
|
||||
export const CLIPROXY_PROVIDER_IDS = Object.freeze(
|
||||
|
||||
@@ -16,7 +16,8 @@ export type CLIProxyProvider =
|
||||
| 'cursor'
|
||||
| 'gitlab'
|
||||
| 'codebuddy'
|
||||
| 'kilo';
|
||||
| 'kilo'
|
||||
| 'qoder';
|
||||
|
||||
/** CLIProxy backend selection */
|
||||
export type CLIProxyBackend = 'original' | 'plus';
|
||||
@@ -32,6 +33,7 @@ export const PLUS_ONLY_PROVIDERS: CLIProxyProvider[] = [
|
||||
'gitlab',
|
||||
'codebuddy',
|
||||
'kilo',
|
||||
'qoder',
|
||||
];
|
||||
|
||||
/** Model mapping for each provider */
|
||||
|
||||
@@ -205,6 +205,7 @@ export const BUILTIN_PROVIDER_SHORTCUTS: readonly ShortcutEntry[] = CLIPROXY_PRO
|
||||
gitlab: 'GitLab Duo via CLIProxy OAuth',
|
||||
codebuddy: 'CodeBuddy via CLIProxy OAuth',
|
||||
kilo: 'Kilo AI via CLIProxy OAuth',
|
||||
qoder: 'Qoder AI via CLIProxy OAuth',
|
||||
}[name] || 'CLIProxy OAuth provider',
|
||||
})
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ export const RESERVED_PROFILE_NAMES = [
|
||||
'gitlab',
|
||||
'codebuddy',
|
||||
'kilo',
|
||||
'qoder',
|
||||
// Copilot API (GitHub Copilot proxy)
|
||||
'copilot',
|
||||
// Cursor IDE (Cursor proxy daemon)
|
||||
|
||||
@@ -97,6 +97,7 @@ describe('ProfileDetector', () => {
|
||||
expect(detector.detectProfileType('gitlab').provider).toBe('gitlab');
|
||||
expect(detector.detectProfileType('codebuddy').provider).toBe('codebuddy');
|
||||
expect(detector.detectProfileType('kilo').provider).toBe('kilo');
|
||||
expect(detector.detectProfileType('qoder').provider).toBe('qoder');
|
||||
});
|
||||
|
||||
it('should detect settings-based profile from unified config', () => {
|
||||
|
||||
@@ -85,6 +85,7 @@ describe('completion backend', () => {
|
||||
expect(values).toContain('gitlab');
|
||||
expect(values).toContain('codebuddy');
|
||||
expect(values).toContain('kilo');
|
||||
expect(values).toContain('qoder');
|
||||
expect(values).toContain('localglm');
|
||||
expect(values).toContain('work');
|
||||
expect(values).toContain('my-codex');
|
||||
|
||||
@@ -61,6 +61,7 @@ describe('help command parity', () => {
|
||||
expect(rendered.includes('gitlab')).toBe(true);
|
||||
expect(rendered.includes('codebuddy')).toBe(true);
|
||||
expect(rendered.includes('kilo')).toBe(true);
|
||||
expect(rendered.includes('qoder')).toBe(true);
|
||||
expect(rendered.includes('--gitlab-token-login')).toBe(true);
|
||||
expect(rendered.includes('--token-login')).toBe(true);
|
||||
expect(rendered.includes('--gitlab-url <url>')).toBe(true);
|
||||
|
||||
@@ -17,6 +17,7 @@ describe('cliproxy-auth-routes start-url guard', () => {
|
||||
"Provider 'codebuddy' uses Device Code flow"
|
||||
);
|
||||
expect(getStartUrlUnsupportedReason('kilo')).toContain("Provider 'kilo' uses Device Code flow");
|
||||
expect(getStartUrlUnsupportedReason('qoder')).toContain("Provider 'qoder' uses Device Code flow");
|
||||
});
|
||||
|
||||
it('allows Cursor browser URL auth on start-url', () => {
|
||||
|
||||
Reference in New Issue
Block a user