diff --git a/src/agents/plugins/claude/claude.plugin.ts b/src/agents/plugins/claude/claude.plugin.ts index 79810d60..b41ad276 100644 --- a/src/agents/plugins/claude/claude.plugin.ts +++ b/src/agents/plugins/claude/claude.plugin.ts @@ -30,17 +30,17 @@ let statuslineManagedThisSession = false; * * **UPDATE THIS WHEN BUMPING CLAUDE VERSION** */ -const CLAUDE_SUPPORTED_VERSION = '2.1.41'; +const CLAUDE_SUPPORTED_VERSION = '2.1.56'; /** * Minimum supported Claude Code version * Versions below this are known to be incompatible and will be blocked from starting * Rule: always 10 patch versions below CLAUDE_SUPPORTED_VERSION - * e.g. supported = 2.1.41 → minimum = 2.1.31 + * e.g. supported = 2.1.56 → minimum = 2.1.41 * * **UPDATE THIS WHEN BUMPING CLAUDE VERSION** */ -const CLAUDE_MINIMUM_SUPPORTED_VERSION = '2.1.32'; +const CLAUDE_MINIMUM_SUPPORTED_VERSION = '2.1.41'; /** * Claude Code installer URLs diff --git a/src/providers/plugins/sso/sso.http-client.ts b/src/providers/plugins/sso/sso.http-client.ts index 1d252b2a..5f7cd77d 100644 --- a/src/providers/plugins/sso/sso.http-client.ts +++ b/src/providers/plugins/sso/sso.http-client.ts @@ -27,7 +27,7 @@ export interface CodeMieUserInfo { */ export const CODEMIE_ENDPOINTS = { MODELS: '/v1/llm_models?include_all=true', - USER_SETTINGS: '/v1/settings/user', + USER_SETTINGS_AVAILABLE: '/v1/settings/user/available', USER: '/v1/user', ADMIN_APPLICATIONS: '/v1/admin/applications', METRICS: '/v1/metrics', @@ -198,65 +198,26 @@ export async function fetchApplicationDetails( } /** - * Fetch integrations from CodeMie SSO API (paginated) + * Fetch integrations from CodeMie SSO API. + * Uses /v1/settings/user/available which returns both user-level and project-level + * integrations in a single call. */ export async function fetchCodeMieIntegrations( apiUrl: string, - cookies: Record, - endpointPath: string = CODEMIE_ENDPOINTS.USER_SETTINGS + cookies: Record ): Promise { const cookieString = Object.entries(cookies) .map(([key, value]) => `${key}=${value}`) .join(';'); - const allIntegrations: CodeMieIntegration[] = []; - let currentPage = 0; - const perPage = 50; - let hasMorePages = true; - let lastError: Error | undefined; - - while (hasMorePages) { - try { - // Build URL with query parameters to filter by LiteLLM type - const filters = JSON.stringify({ type: ['LiteLLM'] }); - const queryParams = new URLSearchParams({ - page: currentPage.toString(), - per_page: perPage.toString(), - filters: filters - }); - - const fullUrl = `${apiUrl}${endpointPath}?${queryParams.toString()}`; - - if (process.env.CODEMIE_DEBUG) { - console.log(`[DEBUG] Fetching integrations from: ${fullUrl}`); - } - - const pageIntegrations = await fetchIntegrationsPage(fullUrl, cookieString); - - if (pageIntegrations.length === 0) { - hasMorePages = false; - } else { - allIntegrations.push(...pageIntegrations); - - // If we got fewer items than requested, we've reached the last page - if (pageIntegrations.length < perPage) { - hasMorePages = false; - } else { - currentPage++; - } - } - } catch (error) { - lastError = error instanceof Error ? error : new Error(String(error)); - hasMorePages = false; - } - } + const fullUrl = `${apiUrl}${CODEMIE_ENDPOINTS.USER_SETTINGS_AVAILABLE}`; - // If we got no integrations and had an error, throw it - if (allIntegrations.length === 0 && lastError) { - throw lastError; + if (process.env.CODEMIE_DEBUG) { + console.log(`[DEBUG] Fetching integrations from: ${fullUrl}`); } - return allIntegrations; + const integrations = await fetchIntegrationsPage(fullUrl, cookieString); + return integrations.filter(i => i.credential_type === 'LiteLLM'); } /** diff --git a/src/providers/plugins/sso/sso.models.ts b/src/providers/plugins/sso/sso.models.ts index 968f46b8..7d0be231 100644 --- a/src/providers/plugins/sso/sso.models.ts +++ b/src/providers/plugins/sso/sso.models.ts @@ -118,17 +118,16 @@ export class SSOModelProxy extends BaseModelProxy { const apiUrl = credentials.apiUrl || codeMieUrl; - logger.debug(`Fetching integrations from: ${apiUrl}${CODEMIE_ENDPOINTS.USER_SETTINGS}`); + logger.debug(`Fetching integrations from: ${apiUrl}${CODEMIE_ENDPOINTS.USER_SETTINGS_AVAILABLE}`); if (projectName) { logger.debug(`Filtering by project: ${projectName}`); } try { - // Fetch all integrations + // Fetch all integrations (user-level + project-level) from a single endpoint const allIntegrations = await fetchCodeMieIntegrations( apiUrl, - credentials.cookies, - CODEMIE_ENDPOINTS.USER_SETTINGS + credentials.cookies ); // Filter by project_name if specified diff --git a/tests/integration/sso-per-url-credentials.test.ts b/tests/integration/sso-per-url-credentials.test.ts index 7ff397ee..07bb7719 100644 --- a/tests/integration/sso-per-url-credentials.test.ts +++ b/tests/integration/sso-per-url-credentials.test.ts @@ -20,7 +20,7 @@ vi.mock('../../src/providers/plugins/sso/sso.http-client.js', () => ({ }), CODEMIE_ENDPOINTS: { MODELS: '/v1/llm_models?include_all=true', - USER_SETTINGS: '/v1/settings/user', + USER_SETTINGS_AVAILABLE: '/v1/settings/user/available', USER: '/v1/user', ADMIN_APPLICATIONS: '/v1/admin/applications', METRICS: '/v1/metrics', @@ -75,7 +75,7 @@ describe('SSO Per-URL Credential Management', () => { }); it('should have correct endpoint paths for all API endpoints', () => { - expect(CODEMIE_ENDPOINTS.USER_SETTINGS).toBe('/v1/settings/user'); + expect(CODEMIE_ENDPOINTS.USER_SETTINGS_AVAILABLE).toBe('/v1/settings/user/available'); expect(CODEMIE_ENDPOINTS.USER).toBe('/v1/user'); expect(CODEMIE_ENDPOINTS.ADMIN_APPLICATIONS).toBe('/v1/admin/applications'); expect(CODEMIE_ENDPOINTS.METRICS).toBe('/v1/metrics');