feat(cliproxy): claude pool gap closure - model-neutral launch, shadow warning, provider ban copy

- claude provider launch env no longer pins ANTHROPIC_MODEL/tier defaults;
  one-shot migration strips CCS-written stale pins across all historically
  shipped default generations while preserving explicit user pins
- TTY-gated once-per-install warning when a user profile named claude or
  anthropic is shadowed by the built-in provider, with rename guidance
- account-safety ban messaging parameterized by provider; Anthropic
  patterns gated to claude accounts only
- first-run notice that ccs claude routes through the local CLIProxy
  instance

Part of #1464 account pools (phase 2).
This commit is contained in:
Tam Nhu Tran committed 2026-06-10 22:57:24 -04:00
1 parent 17849c4a32
commit a257016ebb
14 files changed
+1156 -63

No files matched your search

@@ -91,6 +91,12 @@ export function suggestCliproxyBridgeName(provider: CLIProxyProvider): string {
}
function resolveBridgeModelMapping(provider: CLIProxyProvider): ModelMapping {
// claude is model-neutral: model keys are absent from its base config so that
// Claude Code's own /model selection is respected end-to-end. Return empty
// strings here; createSettingsFile skips writing empty model entries.
if (provider === 'claude') {
return { default: '', opus: '', sonnet: '', haiku: '' };
}
const mapping = getModelMappingFromConfig(provider);
return {
default: mapping.defaultModel,
+18 -8
View File
@@ -109,6 +109,15 @@ function createSettingsFile(
});
const isNative = isAnthropicDirect(baseUrl, apiKey);
// Model-neutral providers (e.g. claude built-in) pass empty strings to signal
// "omit this key". Filter them out so the written settings file does not
// contain ANTHROPIC_MODEL:'' which could be treated as an unintended override.
const modelEnv = {
...(models.default.trim() ? { ANTHROPIC_MODEL: models.default } : {}),
...(models.opus.trim() ? { ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus } : {}),
...(models.sonnet.trim() ? { ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet } : {}),
...(models.haiku.trim() ? { ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku } : {}),
};
const settings = {
env: {
// Native mode: ANTHROPIC_API_KEY only, no BASE_URL/AUTH_TOKEN
@@ -120,10 +129,7 @@ function createSettingsFile(
ANTHROPIC_AUTH_TOKEN: apiKey,
...(isOpenRouterUrl(baseUrl) && { ANTHROPIC_API_KEY: '' }),
}),
ANTHROPIC_MODEL: models.default,
ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus,
ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet,
ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku,
...modelEnv,
...(extraModels && extraModels.length > 0
? { ANTHROPIC_EXTRA_MODELS: extraModels.join(',') }
: {}),
@@ -202,6 +208,13 @@ function createApiProfileUnified(
});
const isNative = isAnthropicDirect(baseUrl, apiKey);
// Model-neutral providers pass empty strings; omit those keys.
const modelEnvUnified = {
...(models.default.trim() ? { ANTHROPIC_MODEL: models.default } : {}),
...(models.opus.trim() ? { ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus } : {}),
...(models.sonnet.trim() ? { ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet } : {}),
...(models.haiku.trim() ? { ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku } : {}),
};
const settings = {
env: {
...(isNative
@@ -211,10 +224,7 @@ function createApiProfileUnified(
ANTHROPIC_AUTH_TOKEN: apiKey,
...(isOpenRouterUrl(baseUrl) && { ANTHROPIC_API_KEY: '' }),
}),
ANTHROPIC_MODEL: models.default,
ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus,
ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet,
ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku,
...modelEnvUnified,
...(extraModels && extraModels.length > 0
? { ANTHROPIC_EXTRA_MODELS: extraModels.join(',') }
: {}),