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

@@ -62,7 +62,7 @@ describe('image-analysis-backend-resolver', () => {
expect(status.supported).toBe(true);
expect(status.backendId).toBe('gemini');
expect(status.resolutionSource).toBe('fallback-backend');
expect(status.model).toBe('gemini-2.5-flash');
expect(status.model).toBe('gemini-3-flash-preview');
});
it('keeps direct Anthropic settings profiles on native read unless explicitly mapped', () => {
@@ -108,6 +108,29 @@ describe('image-analysis-backend-resolver', () => {
expect(status.resolutionSource).toBe('profile-backend');
});
it('lets explicit profile_backends overrides win over cliproxy provider inference', () => {
const config: ImageAnalysisConfig = {
...DEFAULT_IMAGE_ANALYSIS_CONFIG,
profile_backends: {
glmv: 'ghcp',
},
};
const status = resolveImageAnalysisStatus(
{
profileName: 'glmv',
profileType: 'cliproxy',
cliproxyProvider: 'gemini',
},
config
);
expect(status.supported).toBe(true);
expect(status.status).toBe('mapped');
expect(status.backendId).toBe('ghcp');
expect(status.resolutionSource).toBe('profile-backend');
});
it('reports hook-missing when the profile should persist a hook but it is absent', () => {
const status = resolveImageAnalysisStatus(
{
@@ -128,4 +151,32 @@ describe('image-analysis-backend-resolver', () => {
expect(status.status).toBe('hook-missing');
expect(status.reason).toContain('Profile hook is missing');
});
it('prefers native image reading when the profile settings opt into it', () => {
const status = resolveImageAnalysisStatus(
{
profileName: 'glmv',
profileType: 'settings',
settings: {
env: {
ANTHROPIC_BASE_URL: 'https://api.z.ai/v1',
ANTHROPIC_MODEL: 'glm-4.5v',
ANTHROPIC_AUTH_TOKEN: 'glm-test-key',
},
ccs_image: {
native_read: true,
},
},
},
DEFAULT_IMAGE_ANALYSIS_CONFIG
);
expect(status.backendId).toBeNull();
expect(status.resolutionSource).toBe('native-compatible');
expect(status.nativeReadPreference).toBe(true);
expect(status.profileModel).toBe('glm-4.5v');
expect(status.nativeImageCapable).toBe(true);
expect(status.shouldPersistHook).toBe(false);
expect(status.effectiveRuntimeMode).toBe('native-read');
});
});
@@ -27,6 +27,10 @@ function createStatus(overrides: Partial<ImageAnalysisStatus> = {}): ImageAnalys
proxyReason: 'CLIProxy runtime readiness has not been verified yet.',
effectiveRuntimeMode: 'native-read',
effectiveRuntimeReason: null,
profileModel: 'claude-haiku-4.5',
nativeReadPreference: false,
nativeImageCapable: true,
nativeImageReason: 'claude-haiku-4.5 can read images natively.',
...overrides,
};
}