feat(image): add native-read controls and autosave settings

- add per-profile native image preferences and native-capability detection
- redesign Settings -> Image around compact sections with Web-style autosave
- expose richer backend/profile status and update Gemini Flash defaults
This commit is contained in:
Tam Nhu Tran committed 2026-04-01 15:32:37 -04:00
1 parent 9d1d281e34
commit 982ffc5895
30 files changed
+1893 -708

No files matched your search

@@ -101,7 +101,7 @@ describe('image-analysis routes', () => {
enabled: true,
timeout: 60,
provider_models: {
gemini: 'gemini-2.5-flash',
gemini: 'gemini-3-flash-preview',
ghcp: 'claude-haiku-4.5',
},
fallback_backend: 'gemini',
@@ -158,7 +158,7 @@ describe('image-analysis routes', () => {
expect.arrayContaining([
expect.objectContaining({
backendId: 'gemini',
model: 'gemini-2.5-flash',
model: 'gemini-3-flash-preview',
}),
expect.objectContaining({
backendId: 'ghcp',
@@ -227,7 +227,7 @@ describe('image-analysis routes', () => {
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
providerModels: {
gemini: 'gemini-2.5-flash',
gemini: 'gemini-3-flash-preview',
},
fallbackBackend: 'gemini',
profileBackends: {
@@ -111,7 +111,7 @@ describe('settings-routes image-analysis status', () => {
expect(body.imageAnalysisStatus.status).toBe('active');
expect(body.imageAnalysisStatus.backendId).toBe('gemini');
expect(body.imageAnalysisStatus.resolutionSource).toBe('fallback-backend');
expect(body.imageAnalysisStatus.model).toBe('gemini-2.5-flash');
expect(body.imageAnalysisStatus.model).toBe('gemini-3-flash-preview');
expect(body.imageAnalysisStatus.persistencePath).toContain('glm.settings.json');
expect(body.imageAnalysisStatus.authReadiness).toBe('missing');
expect(body.imageAnalysisStatus.effectiveRuntimeMode).toBe('native-read');
@@ -255,4 +255,38 @@ describe('settings-routes image-analysis status', () => {
expect(body.imageAnalysisStatus.resolutionSource).toBe('cliproxy-bridge');
expect(body.imageAnalysisStatus.authReadiness).toBe('missing');
});
it('respects per-profile native image preference stored in settings json', async () => {
writeJson(path.join(tempHome, '.ccs', 'glmv.settings.json'), {
env: {
ANTHROPIC_BASE_URL: 'https://api.z.ai/v1',
ANTHROPIC_MODEL: 'glm-4.5v',
ANTHROPIC_AUTH_TOKEN: 'glmv-test-key',
},
ccs_image: {
native_read: true,
},
});
const response = await fetch(`${baseUrl}/api/settings/glmv/raw`);
expect(response.status).toBe(200);
const body = (await response.json()) as {
imageAnalysisStatus: {
backendId: string | null;
resolutionSource: string;
profileModel: string | null;
nativeReadPreference: boolean;
nativeImageCapable: boolean | null;
effectiveRuntimeMode: string;
};
};
expect(body.imageAnalysisStatus.backendId).toBeNull();
expect(body.imageAnalysisStatus.resolutionSource).toBe('native-compatible');
expect(body.imageAnalysisStatus.profileModel).toBe('glm-4.5v');
expect(body.imageAnalysisStatus.nativeReadPreference).toBe(true);
expect(body.imageAnalysisStatus.nativeImageCapable).toBe(true);
expect(body.imageAnalysisStatus.effectiveRuntimeMode).toBe('native-read');
});
});