mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-04 16:16:46 +00:00
fix(cliproxy): add defensive null checks for composite tier config
- Add optional chaining for tier access in env-resolver - Throw error if default tier model missing in env-builder - Add null checks for composite.tiers in profile-detector
This commit is contained in:
@@ -130,10 +130,27 @@ class ProfileDetector {
|
|||||||
// Handle composite variants
|
// Handle composite variants
|
||||||
if ('type' in variant && variant.type === 'composite') {
|
if ('type' in variant && variant.type === 'composite') {
|
||||||
const composite = variant as CompositeVariantConfig;
|
const composite = variant as CompositeVariantConfig;
|
||||||
|
|
||||||
|
// Defensive: check for missing tiers or default_tier
|
||||||
|
if (!composite.tiers || !composite.default_tier) {
|
||||||
|
console.warn(
|
||||||
|
`[!] Warning: Composite variant '${profileName}' has missing tiers or default_tier`
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultTierConfig = composite.tiers[composite.default_tier];
|
||||||
|
if (!defaultTierConfig) {
|
||||||
|
console.warn(
|
||||||
|
`[!] Warning: Composite variant '${profileName}' missing config for default tier '${composite.default_tier}'`
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'cliproxy',
|
type: 'cliproxy',
|
||||||
name: profileName,
|
name: profileName,
|
||||||
provider: composite.tiers[composite.default_tier].provider as CLIProxyProfileName,
|
provider: defaultTierConfig.provider as CLIProxyProfileName,
|
||||||
settingsPath: composite.settings,
|
settingsPath: composite.settings,
|
||||||
port: composite.port,
|
port: composite.port,
|
||||||
isComposite: true,
|
isComposite: true,
|
||||||
|
|||||||
@@ -461,17 +461,31 @@ export function getCompositeEnvVars(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const validPort = validatePort(port);
|
const validPort = validatePort(port);
|
||||||
const defaultModel = tiers[defaultTier].model;
|
|
||||||
|
|
||||||
return {
|
// Defensive: handle missing tiers gracefully
|
||||||
|
const opusModel = tiers.opus?.model;
|
||||||
|
const sonnetModel = tiers.sonnet?.model;
|
||||||
|
const haikuModel = tiers.haiku?.model;
|
||||||
|
const defaultModel = tiers[defaultTier]?.model;
|
||||||
|
|
||||||
|
// If default tier is missing, we cannot proceed meaningfully
|
||||||
|
if (!defaultModel) {
|
||||||
|
throw new Error(`Missing model for default tier '${defaultTier}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const env: Record<string, string> = {
|
||||||
...globalEnv,
|
...globalEnv,
|
||||||
...additionalEnvVars,
|
...additionalEnvVars,
|
||||||
// Root URL — CLIProxyAPI routes based on model name in request body
|
// Root URL — CLIProxyAPI routes based on model name in request body
|
||||||
ANTHROPIC_BASE_URL: `http://127.0.0.1:${validPort}`,
|
ANTHROPIC_BASE_URL: `http://127.0.0.1:${validPort}`,
|
||||||
ANTHROPIC_AUTH_TOKEN: getEffectiveApiKey(),
|
ANTHROPIC_AUTH_TOKEN: getEffectiveApiKey(),
|
||||||
ANTHROPIC_MODEL: defaultModel,
|
ANTHROPIC_MODEL: defaultModel,
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL: tiers.opus.model,
|
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL: tiers.sonnet.model,
|
|
||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL: tiers.haiku.model,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Only set tier env vars if the tier exists
|
||||||
|
if (opusModel) env.ANTHROPIC_DEFAULT_OPUS_MODEL = opusModel;
|
||||||
|
if (sonnetModel) env.ANTHROPIC_DEFAULT_SONNET_MODEL = sonnetModel;
|
||||||
|
if (haikuModel) env.ANTHROPIC_DEFAULT_HAIKU_MODEL = haikuModel;
|
||||||
|
|
||||||
|
return env;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,9 +136,9 @@ export function buildClaudeEnvironment(config: ProxyChainConfig): Record<string,
|
|||||||
let compositeTierThinking: { opus?: string; sonnet?: string; haiku?: string } | undefined;
|
let compositeTierThinking: { opus?: string; sonnet?: string; haiku?: string } | undefined;
|
||||||
if (isComposite && compositeTiers) {
|
if (isComposite && compositeTiers) {
|
||||||
const tierThinking: { opus?: string; sonnet?: string; haiku?: string } = {};
|
const tierThinking: { opus?: string; sonnet?: string; haiku?: string } = {};
|
||||||
if (compositeTiers.opus.thinking) tierThinking.opus = compositeTiers.opus.thinking;
|
if (compositeTiers.opus?.thinking) tierThinking.opus = compositeTiers.opus.thinking;
|
||||||
if (compositeTiers.sonnet.thinking) tierThinking.sonnet = compositeTiers.sonnet.thinking;
|
if (compositeTiers.sonnet?.thinking) tierThinking.sonnet = compositeTiers.sonnet.thinking;
|
||||||
if (compositeTiers.haiku.thinking) tierThinking.haiku = compositeTiers.haiku.thinking;
|
if (compositeTiers.haiku?.thinking) tierThinking.haiku = compositeTiers.haiku.thinking;
|
||||||
if (Object.keys(tierThinking).length > 0) {
|
if (Object.keys(tierThinking).length > 0) {
|
||||||
compositeTierThinking = tierThinking;
|
compositeTierThinking = tierThinking;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user