fix(cliproxy): fix edit dialog empty model and composite guidance

- P2: Edit dialog no longer seeds empty model string
  Changed `variant.model || ''` to `variant.model ?? undefined`
  Added payload filtering to exclude undefined/empty values before API call
  Prevents unintended model overwrites when user only changes other fields

- P3: Composite --config guidance now uses variant name
  Added profileName to ExecutorConfig interface
  Error message now shows correct variant name instead of default tier provider
  e.g., "ccs cliproxy edit my-mix" instead of "ccs cliproxy edit gemini"
This commit is contained in:
Tam Nhu Tran committed 2026-02-12 12:56:57 +07:00
1 parent 399d7e163a
commit 8e6b67bf99
4 files changed
+12 -4

No files matched your search

+1
View File
@@ -611,6 +611,7 @@ async function main(): Promise<void> {
isComposite: profileInfo.isComposite, isComposite: profileInfo.isComposite,
compositeTiers: profileInfo.compositeTiers, compositeTiers: profileInfo.compositeTiers,
compositeDefaultTier: profileInfo.compositeDefaultTier, compositeDefaultTier: profileInfo.compositeDefaultTier,
profileName: profileInfo.name,
}); });
} else if (profileInfo.type === 'copilot') { } else if (profileInfo.type === 'copilot') {
// COPILOT FLOW: GitHub Copilot subscription via copilot-api proxy // COPILOT FLOW: GitHub Copilot subscription via copilot-api proxy
+2 -1
View File
@@ -434,10 +434,11 @@ export async function execClaudeWithCLIProxy(
if (forceConfig && supportsModelConfig(provider)) { if (forceConfig && supportsModelConfig(provider)) {
// Block --config for composite variants (per-tier models in config.yaml) // Block --config for composite variants (per-tier models in config.yaml)
if (cfg.isComposite) { if (cfg.isComposite) {
const variantName = cfg.profileName || provider;
console.log( console.log(
warn('Composite variants use per-tier config. Edit config.yaml to change tier models.') warn('Composite variants use per-tier config. Edit config.yaml to change tier models.')
); );
console.error(` Use "ccs cliproxy edit ${provider}" to modify composite variants`); console.error(` Use "ccs cliproxy edit ${variantName}" to modify composite variants`);
process.exit(1); process.exit(1);
} else { } else {
await configureProviderModel(provider, true, cfg.customSettingsPath); await configureProviderModel(provider, true, cfg.customSettingsPath);
+2
View File
@@ -193,6 +193,8 @@ export interface ExecutorConfig {
}; };
/** Composite variant: which tier is the default */ /** Composite variant: which tier is the default */
compositeDefaultTier?: 'opus' | 'sonnet' | 'haiku'; compositeDefaultTier?: 'opus' | 'sonnet' | 'haiku';
/** Original profile/variant name (e.g., "my-mix" for composite variants) */
profileName?: string;
} }
/** /**
@@ -90,16 +90,20 @@ export function CliproxyEditDialog({ variant, open, onOpenChange }: CliproxyEdit
} else { } else {
singleForm.reset({ singleForm.reset({
provider: variant.provider, provider: variant.provider,
model: variant.model || '', model: variant.model ?? undefined,
account: variant.account || '', account: variant.account ?? undefined,
}); });
} }
}, [variant, isComposite, singleForm, compositeForm]); }, [variant, isComposite, singleForm, compositeForm]);
const onSubmitSingle = async (data: SingleProviderFormData) => { const onSubmitSingle = async (data: SingleProviderFormData) => {
if (!variant) return; if (!variant) return;
// Filter out undefined values - backend interprets undefined as "no change"
const payload = Object.fromEntries(
Object.entries(data).filter(([, v]) => v !== undefined && v !== '')
) as SingleProviderFormData;
try { try {
await updateMutation.mutateAsync({ name: variant.name, data }); await updateMutation.mutateAsync({ name: variant.name, data: payload });
onOpenChange(false); onOpenChange(false);
} catch (error) { } catch (error) {
console.error('Failed to update variant:', error); console.error('Failed to update variant:', error);