diff --git a/docs/project-roadmap.md b/docs/project-roadmap.md index 82c63df6..7a4ebde8 100644 --- a/docs/project-roadmap.md +++ b/docs/project-roadmap.md @@ -41,6 +41,7 @@ All major modularization work is complete. The codebase evolved from monolithic ### Recent Fixes +- **2026-04-10**: **#944** Image Analysis auth readiness no longer collapses to native Read when a partial runtime-status dependency override omits `initializeAccounts`. CCS now treats account-registry warm-up as optional in that path, still reads token-backed auth status directly, and includes regression coverage for the missing-initializer case so Kimi-backed sessions do not fail on `deps.initializeAccounts is not a function`. - **2026-04-10**: **#945** CCS now normalizes Gemini CLI and Antigravity tier signals around an explicit `free / pro / ultra / unknown` model, preserves raw tier ids such as `g1-pro-tier`, enriches Gemini quota responses with provider entitlement evidence, classifies `MODEL_CAPACITY_EXHAUSTED` separately from auth/entitlement failures, fixes the Antigravity CLI quota table so live quota-derived tiers no longer collapse back to stale `unknown`, adds Gemini tier ids to CLI quota output, extends Gemini Flash Lite grouping to cover `gemini-3.1-flash-lite-preview`, and allows Gemini account surfaces to render the same tier badge semantics as Antigravity. - **2026-04-09**: **#938** Cliproxy model routing now exposes backend-pinned short prefixes for overlapping OAuth backends. CCS repairs managed OAuth auth-file prefixes for Gemini CLI (`gcli`) and Antigravity (`agy`), enriches `/api/cliproxy/catalog` with routing hints that show whether an unprefixed model is safe, shadowed, or prefix-only, upgrades `ccs cliproxy catalog` plus interactive variant model pickers to surface the pinned names, and updates the `ccs config` Cliproxy model selection UI so users can see the preferred call name and current effective backend before saving settings. - **2026-04-08**: **#931** `/cliproxy` model pickers now source their provider catalogs from CLIProxy management model definitions instead of treating the UI catalog file as the dropdown source of truth. CCS now refreshes live model definitions for Gemini, Codex, Claude, Antigravity, Qwen, iFlow, Kiro, GitHub Copilot, and Kimi through `/api/cliproxy/catalog`, overlays CCS-only preset/default metadata on top of those upstream models, keeps `/api/cliproxy/models` as the live availability feed, and falls back to cached/static catalogs when the proxy is unavailable so the dashboard never goes blank. diff --git a/src/utils/hooks/image-analysis-runtime-status.ts b/src/utils/hooks/image-analysis-runtime-status.ts index 9ec8a388..8d40532f 100644 --- a/src/utils/hooks/image-analysis-runtime-status.ts +++ b/src/utils/hooks/image-analysis-runtime-status.ts @@ -64,7 +64,9 @@ async function resolveAuthReadiness( (entry) => entry.provider === authProvider && entry.authenticated ); } else { - deps.initializeAccounts(); + if (typeof deps.initializeAccounts === 'function') { + deps.initializeAccounts(); + } authenticated = deps.getAuthStatus(authProvider).authenticated; } diff --git a/tests/unit/utils/hooks/image-analysis-runtime-status.test.ts b/tests/unit/utils/hooks/image-analysis-runtime-status.test.ts index ccb02d26..d314eb7a 100644 --- a/tests/unit/utils/hooks/image-analysis-runtime-status.test.ts +++ b/tests/unit/utils/hooks/image-analysis-runtime-status.test.ts @@ -88,6 +88,25 @@ describe('image-analysis-runtime-status', () => { expect(status.effectiveRuntimeMode).toBe('cliproxy-image-analysis'); }); + it('uses getAuthStatus when initializeAccounts is omitted from an override', async () => { + const status = await hydrateImageAnalysisRuntimeStatus(createStatus(), { + getProxyTarget: () => ({ host: '127.0.0.1', port: 8317, protocol: 'http', isRemote: false }), + initializeAccounts: undefined as unknown as () => void, + getAuthStatus: () => ({ + provider: 'ghcp', + authenticated: true, + tokenDir: '/tmp/auth', + tokenFiles: ['github-copilot-test.json'], + accounts: [], + defaultAccount: undefined, + }), + isCliproxyRunning: async () => true, + }); + + expect(status.authReadiness).toBe('ready'); + expect(status.effectiveRuntimeMode).toBe('cliproxy-image-analysis'); + }); + it('treats an unreachable remote proxy as unavailable', async () => { const status = await hydrateImageAnalysisRuntimeStatus(createStatus(), { getProxyTarget: () => ({