mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-20 05:11:48 +00:00
refactor(hooks): use provider_models mapping for image analysis
Changes ImageAnalysisConfig from providers array to provider_models mapping for granular vision model control per CLIProxy provider. Breaking change: config.yaml image_analysis section now uses provider_models instead of providers/model fields. Provider-to-model mappings: - agy → gemini-2.5-flash - gemini → gemini-2.5-flash - codex → gpt-5.1-codex-mini - kiro → kiro-claude-haiku-4-5 - ghcp → claude-haiku-4.5 - claude → claude-haiku-4-5-20251001 Hook checks CCS_CURRENT_PROVIDER against provider_models and skips if no vision model configured for that provider.
This commit is contained in:
1 parent
9662490a74
commit
40caff13ad
6 files changed
+113
-30
No files matched your search
@@ -38,6 +38,7 @@ import { configureProviderModel, getCurrentModel } from './model-config';
|
||||
import { resolveProxyConfig, PROXY_CLI_FLAGS } from './proxy-config-resolver';
|
||||
import { getWebSearchHookEnv } from '../utils/websearch-manager';
|
||||
import { getImageReadBlockHookEnv } from '../utils/hooks/image-read-block-hook-env';
|
||||
import { getImageAnalysisHookEnv } from '../utils/hooks/get-image-analysis-hook-env';
|
||||
import { supportsModelConfig, isModelBroken, getModelIssueUrl, findModel } from './model-catalog';
|
||||
import { CodexReasoningProxy } from './codex-reasoning-proxy';
|
||||
import { ToolSanitizationProxy } from './tool-sanitization-proxy';
|
||||
@@ -946,11 +947,13 @@ export async function execClaudeWithCLIProxy(
|
||||
};
|
||||
const webSearchEnv = getWebSearchHookEnv();
|
||||
const imageReadBlockEnv = getImageReadBlockHookEnv();
|
||||
const imageAnalysisEnv = getImageAnalysisHookEnv(provider);
|
||||
const env = {
|
||||
...process.env,
|
||||
...effectiveEnvVars,
|
||||
...webSearchEnv,
|
||||
...imageReadBlockEnv,
|
||||
...imageAnalysisEnv,
|
||||
CCS_PROFILE_TYPE: 'cliproxy', // Signal to WebSearch hook this is a third-party provider
|
||||
};
|
||||
|
||||
|
||||
@@ -298,9 +298,9 @@ function mergeWithDefaults(partial: Partial<UnifiedConfig>): UnifiedConfig {
|
||||
// Image analysis config - enabled by default for CLIProxy providers
|
||||
image_analysis: {
|
||||
enabled: partial.image_analysis?.enabled ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.enabled,
|
||||
model: partial.image_analysis?.model ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.model,
|
||||
timeout: partial.image_analysis?.timeout ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.timeout,
|
||||
providers: partial.image_analysis?.providers ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.providers,
|
||||
provider_models:
|
||||
partial.image_analysis?.provider_models ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.provider_models,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -740,8 +740,8 @@ export function getImageAnalysisConfig(): ImageAnalysisConfig {
|
||||
|
||||
return {
|
||||
enabled: config.image_analysis?.enabled ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.enabled,
|
||||
model: config.image_analysis?.model ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.model,
|
||||
timeout: config.image_analysis?.timeout ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.timeout,
|
||||
providers: config.image_analysis?.providers ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.providers,
|
||||
provider_models:
|
||||
config.image_analysis?.provider_models ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.provider_models,
|
||||
};
|
||||
}
|
||||
@@ -523,14 +523,12 @@ export const DEFAULT_DASHBOARD_AUTH_CONFIG: DashboardAuthConfig = {
|
||||
* Routes image/PDF files through CLIProxy for vision analysis.
|
||||
*/
|
||||
export interface ImageAnalysisConfig {
|
||||
/** Enable image analysis via CLIProxy (default: true for agy/gemini) */
|
||||
/** Enable image analysis via CLIProxy (default: true) */
|
||||
enabled: boolean;
|
||||
/** Model to use for analysis (default: gemini-2.5-flash) */
|
||||
model: string;
|
||||
/** Timeout in seconds (default: 60) */
|
||||
timeout: number;
|
||||
/** Providers to enable for (default: ['agy', 'gemini']) */
|
||||
providers: string[];
|
||||
/** Provider-to-model mapping for vision analysis */
|
||||
provider_models: Record<string, string>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -539,9 +537,15 @@ export interface ImageAnalysisConfig {
|
||||
*/
|
||||
export const DEFAULT_IMAGE_ANALYSIS_CONFIG: ImageAnalysisConfig = {
|
||||
enabled: true,
|
||||
model: 'gemini-2.5-flash',
|
||||
timeout: 60,
|
||||
providers: ['agy', 'gemini'],
|
||||
provider_models: {
|
||||
agy: 'gemini-2.5-flash',
|
||||
gemini: 'gemini-2.5-flash',
|
||||
codex: 'gpt-5.1-codex-mini',
|
||||
kiro: 'kiro-claude-haiku-4-5',
|
||||
ghcp: 'claude-haiku-4.5',
|
||||
claude: 'claude-haiku-4-5-20251001',
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,25 +9,34 @@
|
||||
|
||||
import { getImageAnalysisConfig } from '../../config/unified-config-loader';
|
||||
|
||||
/**
|
||||
* Serialize provider_models map to env var format: provider:model,provider:model
|
||||
*/
|
||||
function serializeProviderModels(providerModels: Record<string, string>): string {
|
||||
return Object.entries(providerModels)
|
||||
.map(([provider, model]) => `${provider}:${model}`)
|
||||
.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image analysis hook environment variables.
|
||||
* These env vars control the hook's behavior via Claude Code hook system.
|
||||
*
|
||||
* @param profileName - Current profile name (to determine if native Claude)
|
||||
* @param provider - Current CLIProxy provider (e.g., 'agy', 'gemini', 'codex')
|
||||
* @returns Environment variables for image analysis hook
|
||||
*/
|
||||
export function getImageAnalysisHookEnv(profileName?: string): Record<string, string> {
|
||||
export function getImageAnalysisHookEnv(provider?: string): Record<string, string> {
|
||||
const config = getImageAnalysisConfig();
|
||||
|
||||
// Native Claude profiles (no CLIProxy) should skip image analysis
|
||||
const isNativeProfile = !profileName || ['claude', 'anthropic'].includes(profileName);
|
||||
const skipImageAnalysis = isNativeProfile || !config.enabled;
|
||||
// Check if current provider has a vision model configured
|
||||
const hasVisionModel = provider && config.provider_models[provider];
|
||||
const skipImageAnalysis = !config.enabled || !hasVisionModel;
|
||||
|
||||
return {
|
||||
CCS_IMAGE_ANALYSIS_ENABLED: config.enabled ? '1' : '0',
|
||||
CCS_IMAGE_ANALYSIS_MODEL: config.model || 'gemini-2.5-flash',
|
||||
CCS_IMAGE_ANALYSIS_TIMEOUT: String(Number(config.timeout) || 60),
|
||||
CCS_IMAGE_ANALYSIS_PROVIDERS: config.providers.join(','),
|
||||
CCS_IMAGE_ANALYSIS_PROVIDER_MODELS: serializeProviderModels(config.provider_models),
|
||||
CCS_CURRENT_PROVIDER: provider || '',
|
||||
CCS_IMAGE_ANALYSIS_SKIP: skipImageAnalysis ? '1' : '0',
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user