refactor(models): migrate to granular model configuration architecture
Upgrade Claude model configuration from dual-key to quad-key system for better model tier differentiation. **Breaking Changes:** - Replace `ANTHROPIC_SMALL_FAST_MODEL` with three granular keys: - `ANTHROPIC_DEFAULT_HAIKU_MODEL` - `ANTHROPIC_DEFAULT_SONNET_MODEL` - `ANTHROPIC_DEFAULT_OPUS_MODEL` **Backend (Rust):** - Add `normalize_claude_models_in_value()` for automatic migration - Implement fallback chain: `DEFAULT_* || SMALL_FAST || MODEL` - Auto-cleanup: remove legacy `SMALL_FAST` key after normalization - Apply normalization across 6 critical paths: - Add/update provider - Read from live config - Write to live config - Refresh config snapshot **Frontend (React):** - Expand UI from 2 to 4 model input fields - Implement smart fallback in `useModelState` hook - Update `useKimiModelSelector` for Kimi model picker - Add i18n keys for Haiku/Sonnet/Opus labels (zh/en) **Configuration:** - Update all 7 provider presets to new format - DeepSeek/Qwen/Moonshot: use same model for all tiers - Zhipu: preserve tier differentiation (glm-4.5-air for Haiku) **Backward Compatibility:** - Old configs auto-upgrade on first read/write - Fallback chain ensures graceful degradation - No manual migration required Closes #[issue-number]
This commit is contained in:
@@ -112,6 +112,74 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ProviderService {
|
impl ProviderService {
|
||||||
|
/// 归一化 Claude 模型键:读旧键(ANTHROPIC_SMALL_FAST_MODEL),写新键(DEFAULT_*), 并删除旧键
|
||||||
|
fn normalize_claude_models_in_value(settings: &mut Value) -> bool {
|
||||||
|
let mut changed = false;
|
||||||
|
let env = match settings.get_mut("env") {
|
||||||
|
Some(v) if v.is_object() => v.as_object_mut().unwrap(),
|
||||||
|
_ => return changed,
|
||||||
|
};
|
||||||
|
|
||||||
|
let model = env
|
||||||
|
.get("ANTHROPIC_MODEL")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
let small_fast = env
|
||||||
|
.get("ANTHROPIC_SMALL_FAST_MODEL")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
|
||||||
|
let current_haiku = env
|
||||||
|
.get("ANTHROPIC_DEFAULT_HAIKU_MODEL")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
let current_sonnet = env
|
||||||
|
.get("ANTHROPIC_DEFAULT_SONNET_MODEL")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
let current_opus = env
|
||||||
|
.get("ANTHROPIC_DEFAULT_OPUS_MODEL")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
|
||||||
|
let target_haiku = current_haiku.or_else(|| small_fast.clone()).or_else(|| model.clone());
|
||||||
|
let target_sonnet = current_sonnet.or_else(|| model.clone()).or_else(|| small_fast.clone());
|
||||||
|
let target_opus = current_opus.or_else(|| model.clone()).or_else(|| small_fast.clone());
|
||||||
|
|
||||||
|
if env.get("ANTHROPIC_DEFAULT_HAIKU_MODEL").is_none() {
|
||||||
|
if let Some(v) = target_haiku {
|
||||||
|
env.insert("ANTHROPIC_DEFAULT_HAIKU_MODEL".to_string(), Value::String(v));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if env.get("ANTHROPIC_DEFAULT_SONNET_MODEL").is_none() {
|
||||||
|
if let Some(v) = target_sonnet {
|
||||||
|
env.insert("ANTHROPIC_DEFAULT_SONNET_MODEL".to_string(), Value::String(v));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if env.get("ANTHROPIC_DEFAULT_OPUS_MODEL").is_none() {
|
||||||
|
if let Some(v) = target_opus {
|
||||||
|
env.insert("ANTHROPIC_DEFAULT_OPUS_MODEL".to_string(), Value::String(v));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if env.remove("ANTHROPIC_SMALL_FAST_MODEL").is_some() {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalize_provider_if_claude(app_type: &AppType, provider: &mut Provider) {
|
||||||
|
if matches!(app_type, AppType::Claude) {
|
||||||
|
let mut v = provider.settings_config.clone();
|
||||||
|
if Self::normalize_claude_models_in_value(&mut v) {
|
||||||
|
provider.settings_config = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fn run_transaction<R, F>(state: &AppState, f: F) -> Result<R, AppError>
|
fn run_transaction<R, F>(state: &AppState, f: F) -> Result<R, AppError>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut MultiAppConfig) -> Result<(R, Option<PostCommitAction>), AppError>,
|
F: FnOnce(&mut MultiAppConfig) -> Result<(R, Option<PostCommitAction>), AppError>,
|
||||||
@@ -209,7 +277,8 @@ impl ProviderService {
|
|||||||
"Claude settings file missing; cannot refresh snapshot",
|
"Claude settings file missing; cannot refresh snapshot",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let live_after = read_json_file::<Value>(&settings_path)?;
|
let mut live_after = read_json_file::<Value>(&settings_path)?;
|
||||||
|
let _ = Self::normalize_claude_models_in_value(&mut live_after);
|
||||||
{
|
{
|
||||||
let mut guard = state.config.write().map_err(AppError::from)?;
|
let mut guard = state.config.write().map_err(AppError::from)?;
|
||||||
if let Some(manager) = guard.get_manager_mut(app_type) {
|
if let Some(manager) = guard.get_manager_mut(app_type) {
|
||||||
@@ -308,6 +377,9 @@ impl ProviderService {
|
|||||||
|
|
||||||
/// 新增供应商
|
/// 新增供应商
|
||||||
pub fn add(state: &AppState, app_type: AppType, provider: Provider) -> Result<bool, AppError> {
|
pub fn add(state: &AppState, app_type: AppType, provider: Provider) -> Result<bool, AppError> {
|
||||||
|
let mut provider = provider;
|
||||||
|
// 归一化 Claude 模型键
|
||||||
|
Self::normalize_provider_if_claude(&app_type, &mut provider);
|
||||||
Self::validate_provider_settings(&app_type, &provider)?;
|
Self::validate_provider_settings(&app_type, &provider)?;
|
||||||
|
|
||||||
let app_type_clone = app_type.clone();
|
let app_type_clone = app_type.clone();
|
||||||
@@ -347,6 +419,9 @@ impl ProviderService {
|
|||||||
app_type: AppType,
|
app_type: AppType,
|
||||||
provider: Provider,
|
provider: Provider,
|
||||||
) -> Result<bool, AppError> {
|
) -> Result<bool, AppError> {
|
||||||
|
let mut provider = provider;
|
||||||
|
// 归一化 Claude 模型键
|
||||||
|
Self::normalize_provider_if_claude(&app_type, &mut provider);
|
||||||
Self::validate_provider_settings(&app_type, &provider)?;
|
Self::validate_provider_settings(&app_type, &provider)?;
|
||||||
let provider_id = provider.id.clone();
|
let provider_id = provider.id.clone();
|
||||||
let app_type_clone = app_type.clone();
|
let app_type_clone = app_type.clone();
|
||||||
@@ -440,7 +515,9 @@ impl ProviderService {
|
|||||||
"Claude settings file is missing",
|
"Claude settings file is missing",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
read_json_file(&settings_path)?
|
let mut v = read_json_file::<Value>(&settings_path)?;
|
||||||
|
let _ = Self::normalize_claude_models_in_value(&mut v);
|
||||||
|
v
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -848,7 +925,8 @@ impl ProviderService {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let live = read_json_file::<Value>(&settings_path)?;
|
let mut live = read_json_file::<Value>(&settings_path)?;
|
||||||
|
let _ = Self::normalize_claude_models_in_value(&mut live);
|
||||||
if let Some(manager) = config.get_manager_mut(&AppType::Claude) {
|
if let Some(manager) = config.get_manager_mut(&AppType::Claude) {
|
||||||
if let Some(current) = manager.providers.get_mut(¤t_id) {
|
if let Some(current) = manager.providers.get_mut(¤t_id) {
|
||||||
current.settings_config = live;
|
current.settings_config = live;
|
||||||
@@ -864,7 +942,10 @@ impl ProviderService {
|
|||||||
std::fs::create_dir_all(parent).map_err(|e| AppError::io(parent, e))?;
|
std::fs::create_dir_all(parent).map_err(|e| AppError::io(parent, e))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_json_file(&settings_path, &provider.settings_config)?;
|
// 归一化后再写入
|
||||||
|
let mut content = provider.settings_config.clone();
|
||||||
|
let _ = Self::normalize_claude_models_in_value(&mut content);
|
||||||
|
write_json_file(&settings_path, &content)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,17 +38,29 @@ interface ClaudeFormFieldsProps {
|
|||||||
shouldShowKimiSelector: boolean;
|
shouldShowKimiSelector: boolean;
|
||||||
shouldShowModelSelector: boolean;
|
shouldShowModelSelector: boolean;
|
||||||
claudeModel: string;
|
claudeModel: string;
|
||||||
claudeSmallFastModel: string;
|
defaultHaikuModel: string;
|
||||||
|
defaultSonnetModel: string;
|
||||||
|
defaultOpusModel: string;
|
||||||
onModelChange: (
|
onModelChange: (
|
||||||
field: "ANTHROPIC_MODEL" | "ANTHROPIC_SMALL_FAST_MODEL",
|
field:
|
||||||
|
| "ANTHROPIC_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_HAIKU_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_SONNET_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_OPUS_MODEL",
|
||||||
value: string,
|
value: string,
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
// Kimi Model Selector
|
// Kimi Model Selector
|
||||||
kimiAnthropicModel: string;
|
kimiAnthropicModel: string;
|
||||||
kimiAnthropicSmallFastModel: string;
|
kimiDefaultHaikuModel: string;
|
||||||
|
kimiDefaultSonnetModel: string;
|
||||||
|
kimiDefaultOpusModel: string;
|
||||||
onKimiModelChange: (
|
onKimiModelChange: (
|
||||||
field: "ANTHROPIC_MODEL" | "ANTHROPIC_SMALL_FAST_MODEL",
|
field:
|
||||||
|
| "ANTHROPIC_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_HAIKU_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_SONNET_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_OPUS_MODEL",
|
||||||
value: string,
|
value: string,
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
@@ -76,10 +88,14 @@ export function ClaudeFormFields({
|
|||||||
shouldShowKimiSelector,
|
shouldShowKimiSelector,
|
||||||
shouldShowModelSelector,
|
shouldShowModelSelector,
|
||||||
claudeModel,
|
claudeModel,
|
||||||
claudeSmallFastModel,
|
defaultHaikuModel,
|
||||||
|
defaultSonnetModel,
|
||||||
|
defaultOpusModel,
|
||||||
onModelChange,
|
onModelChange,
|
||||||
kimiAnthropicModel,
|
kimiAnthropicModel,
|
||||||
kimiAnthropicSmallFastModel,
|
kimiDefaultHaikuModel,
|
||||||
|
kimiDefaultSonnetModel,
|
||||||
|
kimiDefaultOpusModel,
|
||||||
onKimiModelChange,
|
onKimiModelChange,
|
||||||
speedTestEndpoints,
|
speedTestEndpoints,
|
||||||
}: ClaudeFormFieldsProps) {
|
}: ClaudeFormFieldsProps) {
|
||||||
@@ -163,19 +179,53 @@ export function ClaudeFormFields({
|
|||||||
{shouldShowModelSelector && (
|
{shouldShowModelSelector && (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
{/* ANTHROPIC_MODEL */}
|
{/* 主模型 */}
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<FormLabel htmlFor="claudeModel">
|
<FormLabel htmlFor="claudeModel">
|
||||||
{t("providerForm.anthropicModel", {
|
{t("providerForm.anthropicModel", { defaultValue: "主模型" })}
|
||||||
defaultValue: "主模型",
|
|
||||||
})}
|
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
id="claudeModel"
|
id="claudeModel"
|
||||||
type="text"
|
type="text"
|
||||||
value={claudeModel}
|
value={claudeModel}
|
||||||
|
onChange={(e) => onModelChange("ANTHROPIC_MODEL", e.target.value)}
|
||||||
|
placeholder={t("providerForm.modelPlaceholder", {
|
||||||
|
defaultValue: "claude-3-7-sonnet-20250219",
|
||||||
|
})}
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 默认 Haiku */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<FormLabel htmlFor="claudeDefaultHaikuModel">
|
||||||
|
{t("providerForm.anthropicDefaultHaikuModel", { defaultValue: "Haiku 默认模型" })}
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
id="claudeDefaultHaikuModel"
|
||||||
|
type="text"
|
||||||
|
value={defaultHaikuModel}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
onModelChange("ANTHROPIC_MODEL", e.target.value)
|
onModelChange("ANTHROPIC_DEFAULT_HAIKU_MODEL", e.target.value)
|
||||||
|
}
|
||||||
|
placeholder={t("providerForm.modelPlaceholder", {
|
||||||
|
defaultValue: "claude-3-5-haiku-20241022",
|
||||||
|
})}
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 默认 Sonnet */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<FormLabel htmlFor="claudeDefaultSonnetModel">
|
||||||
|
{t("providerForm.anthropicDefaultSonnetModel", { defaultValue: "Sonnet 默认模型" })}
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
id="claudeDefaultSonnetModel"
|
||||||
|
type="text"
|
||||||
|
value={defaultSonnetModel}
|
||||||
|
onChange={(e) =>
|
||||||
|
onModelChange("ANTHROPIC_DEFAULT_SONNET_MODEL", e.target.value)
|
||||||
}
|
}
|
||||||
placeholder={t("providerForm.modelPlaceholder", {
|
placeholder={t("providerForm.modelPlaceholder", {
|
||||||
defaultValue: "claude-3-7-sonnet-20250219",
|
defaultValue: "claude-3-7-sonnet-20250219",
|
||||||
@@ -184,22 +234,20 @@ export function ClaudeFormFields({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ANTHROPIC_SMALL_FAST_MODEL */}
|
{/* 默认 Opus */}
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<FormLabel htmlFor="claudeSmallFastModel">
|
<FormLabel htmlFor="claudeDefaultOpusModel">
|
||||||
{t("providerForm.anthropicSmallFastModel", {
|
{t("providerForm.anthropicDefaultOpusModel", { defaultValue: "Opus 默认模型" })}
|
||||||
defaultValue: "快速模型",
|
|
||||||
})}
|
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
id="claudeSmallFastModel"
|
id="claudeDefaultOpusModel"
|
||||||
type="text"
|
type="text"
|
||||||
value={claudeSmallFastModel}
|
value={defaultOpusModel}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
onModelChange("ANTHROPIC_SMALL_FAST_MODEL", e.target.value)
|
onModelChange("ANTHROPIC_DEFAULT_OPUS_MODEL", e.target.value)
|
||||||
}
|
}
|
||||||
placeholder={t("providerForm.smallModelPlaceholder", {
|
placeholder={t("providerForm.modelPlaceholder", {
|
||||||
defaultValue: "claude-3-5-haiku-20241022",
|
defaultValue: "claude-3-7-opus-20250219",
|
||||||
})}
|
})}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
/>
|
/>
|
||||||
@@ -207,8 +255,7 @@ export function ClaudeFormFields({
|
|||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
{t("providerForm.modelHelper", {
|
{t("providerForm.modelHelper", {
|
||||||
defaultValue:
|
defaultValue: "可选:指定默认使用的 Claude 模型,留空则使用系统默认。",
|
||||||
"可选:指定默认使用的 Claude 模型,留空则使用系统默认。",
|
|
||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -219,7 +266,9 @@ export function ClaudeFormFields({
|
|||||||
<KimiModelSelector
|
<KimiModelSelector
|
||||||
apiKey={apiKey}
|
apiKey={apiKey}
|
||||||
anthropicModel={kimiAnthropicModel}
|
anthropicModel={kimiAnthropicModel}
|
||||||
anthropicSmallFastModel={kimiAnthropicSmallFastModel}
|
defaultHaikuModel={kimiDefaultHaikuModel}
|
||||||
|
defaultSonnetModel={kimiDefaultSonnetModel}
|
||||||
|
defaultOpusModel={kimiDefaultOpusModel}
|
||||||
onModelChange={onKimiModelChange}
|
onModelChange={onKimiModelChange}
|
||||||
disabled={category === "official"}
|
disabled={category === "official"}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -12,9 +12,15 @@ interface KimiModel {
|
|||||||
interface KimiModelSelectorProps {
|
interface KimiModelSelectorProps {
|
||||||
apiKey: string;
|
apiKey: string;
|
||||||
anthropicModel: string;
|
anthropicModel: string;
|
||||||
anthropicSmallFastModel: string;
|
defaultHaikuModel: string;
|
||||||
|
defaultSonnetModel: string;
|
||||||
|
defaultOpusModel: string;
|
||||||
onModelChange: (
|
onModelChange: (
|
||||||
field: "ANTHROPIC_MODEL" | "ANTHROPIC_SMALL_FAST_MODEL",
|
field:
|
||||||
|
| "ANTHROPIC_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_HAIKU_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_SONNET_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_OPUS_MODEL",
|
||||||
value: string,
|
value: string,
|
||||||
) => void;
|
) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@@ -23,7 +29,9 @@ interface KimiModelSelectorProps {
|
|||||||
const KimiModelSelector: React.FC<KimiModelSelectorProps> = ({
|
const KimiModelSelector: React.FC<KimiModelSelectorProps> = ({
|
||||||
apiKey,
|
apiKey,
|
||||||
anthropicModel,
|
anthropicModel,
|
||||||
anthropicSmallFastModel,
|
defaultHaikuModel,
|
||||||
|
defaultSonnetModel,
|
||||||
|
defaultOpusModel,
|
||||||
onModelChange,
|
onModelChange,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -173,11 +181,19 @@ const KimiModelSelector: React.FC<KimiModelSelectorProps> = ({
|
|||||||
onChange={(value) => onModelChange("ANTHROPIC_MODEL", value)}
|
onChange={(value) => onModelChange("ANTHROPIC_MODEL", value)}
|
||||||
/>
|
/>
|
||||||
<ModelSelect
|
<ModelSelect
|
||||||
label={t("kimiSelector.fastModel")}
|
label={t("kimiSelector.haikuModel", { defaultValue: "Haiku 默认" })}
|
||||||
value={anthropicSmallFastModel}
|
value={defaultHaikuModel}
|
||||||
onChange={(value) =>
|
onChange={(value) => onModelChange("ANTHROPIC_DEFAULT_HAIKU_MODEL", value)}
|
||||||
onModelChange("ANTHROPIC_SMALL_FAST_MODEL", value)
|
/>
|
||||||
}
|
<ModelSelect
|
||||||
|
label={t("kimiSelector.sonnetModel", { defaultValue: "Sonnet 默认" })}
|
||||||
|
value={defaultSonnetModel}
|
||||||
|
onChange={(value) => onModelChange("ANTHROPIC_DEFAULT_SONNET_MODEL", value)}
|
||||||
|
/>
|
||||||
|
<ModelSelect
|
||||||
|
label={t("kimiSelector.opusModel", { defaultValue: "Opus 默认" })}
|
||||||
|
value={defaultOpusModel}
|
||||||
|
onChange={(value) => onModelChange("ANTHROPIC_DEFAULT_OPUS_MODEL", value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -140,12 +140,17 @@ export function ProviderForm({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用 Model hook
|
// 使用 Model hook(新:主模型 + Haiku/Sonnet/Opus 默认模型)
|
||||||
const { claudeModel, claudeSmallFastModel, handleModelChange } =
|
const {
|
||||||
useModelState({
|
claudeModel,
|
||||||
settingsConfig: form.watch("settingsConfig"),
|
defaultHaikuModel,
|
||||||
onConfigChange: (config) => form.setValue("settingsConfig", config),
|
defaultSonnetModel,
|
||||||
});
|
defaultOpusModel,
|
||||||
|
handleModelChange,
|
||||||
|
} = useModelState({
|
||||||
|
settingsConfig: form.watch("settingsConfig"),
|
||||||
|
onConfigChange: (config) => form.setValue("settingsConfig", config),
|
||||||
|
});
|
||||||
|
|
||||||
// 使用 Codex 配置 hook (仅 Codex 模式)
|
// 使用 Codex 配置 hook (仅 Codex 模式)
|
||||||
const {
|
const {
|
||||||
@@ -218,7 +223,9 @@ export function ProviderForm({
|
|||||||
const {
|
const {
|
||||||
shouldShow: shouldShowKimiSelector,
|
shouldShow: shouldShowKimiSelector,
|
||||||
kimiAnthropicModel,
|
kimiAnthropicModel,
|
||||||
kimiAnthropicSmallFastModel,
|
kimiDefaultHaikuModel,
|
||||||
|
kimiDefaultSonnetModel,
|
||||||
|
kimiDefaultOpusModel,
|
||||||
handleKimiModelChange,
|
handleKimiModelChange,
|
||||||
} = useKimiModelSelector({
|
} = useKimiModelSelector({
|
||||||
initialData,
|
initialData,
|
||||||
@@ -500,10 +507,14 @@ export function ProviderForm({
|
|||||||
category !== "official" && !shouldShowKimiSelector
|
category !== "official" && !shouldShowKimiSelector
|
||||||
}
|
}
|
||||||
claudeModel={claudeModel}
|
claudeModel={claudeModel}
|
||||||
claudeSmallFastModel={claudeSmallFastModel}
|
defaultHaikuModel={defaultHaikuModel}
|
||||||
|
defaultSonnetModel={defaultSonnetModel}
|
||||||
|
defaultOpusModel={defaultOpusModel}
|
||||||
onModelChange={handleModelChange}
|
onModelChange={handleModelChange}
|
||||||
kimiAnthropicModel={kimiAnthropicModel}
|
kimiAnthropicModel={kimiAnthropicModel}
|
||||||
kimiAnthropicSmallFastModel={kimiAnthropicSmallFastModel}
|
kimiDefaultHaikuModel={kimiDefaultHaikuModel}
|
||||||
|
kimiDefaultSonnetModel={kimiDefaultSonnetModel}
|
||||||
|
kimiDefaultOpusModel={kimiDefaultOpusModel}
|
||||||
onKimiModelChange={handleKimiModelChange}
|
onKimiModelChange={handleKimiModelChange}
|
||||||
speedTestEndpoints={speedTestEndpoints}
|
speedTestEndpoints={speedTestEndpoints}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ export function useKimiModelSelector({
|
|||||||
presetName = "",
|
presetName = "",
|
||||||
}: UseKimiModelSelectorProps) {
|
}: UseKimiModelSelectorProps) {
|
||||||
const [kimiAnthropicModel, setKimiAnthropicModel] = useState("");
|
const [kimiAnthropicModel, setKimiAnthropicModel] = useState("");
|
||||||
const [kimiAnthropicSmallFastModel, setKimiAnthropicSmallFastModel] =
|
const [kimiDefaultHaikuModel, setKimiDefaultHaikuModel] = useState("");
|
||||||
useState("");
|
const [kimiDefaultSonnetModel, setKimiDefaultSonnetModel] = useState("");
|
||||||
|
const [kimiDefaultOpusModel, setKimiDefaultOpusModel] = useState("");
|
||||||
|
|
||||||
// 判断是否显示 Kimi 模型选择器
|
// 判断是否显示 Kimi 模型选择器
|
||||||
const shouldShowKimiSelector =
|
const shouldShowKimiSelector =
|
||||||
@@ -53,12 +54,24 @@ export function useKimiModelSelector({
|
|||||||
typeof config.env.ANTHROPIC_MODEL === "string"
|
typeof config.env.ANTHROPIC_MODEL === "string"
|
||||||
? config.env.ANTHROPIC_MODEL
|
? config.env.ANTHROPIC_MODEL
|
||||||
: "";
|
: "";
|
||||||
const smallFastModel =
|
const haiku =
|
||||||
typeof config.env.ANTHROPIC_SMALL_FAST_MODEL === "string"
|
typeof config.env.ANTHROPIC_DEFAULT_HAIKU_MODEL === "string"
|
||||||
? config.env.ANTHROPIC_SMALL_FAST_MODEL
|
? (config.env.ANTHROPIC_DEFAULT_HAIKU_MODEL as string)
|
||||||
: "";
|
: (typeof config.env.ANTHROPIC_SMALL_FAST_MODEL === "string"
|
||||||
|
? (config.env.ANTHROPIC_SMALL_FAST_MODEL as string)
|
||||||
|
: model);
|
||||||
|
const sonnet =
|
||||||
|
typeof config.env.ANTHROPIC_DEFAULT_SONNET_MODEL === "string"
|
||||||
|
? (config.env.ANTHROPIC_DEFAULT_SONNET_MODEL as string)
|
||||||
|
: model;
|
||||||
|
const opus =
|
||||||
|
typeof config.env.ANTHROPIC_DEFAULT_OPUS_MODEL === "string"
|
||||||
|
? (config.env.ANTHROPIC_DEFAULT_OPUS_MODEL as string)
|
||||||
|
: model;
|
||||||
setKimiAnthropicModel(model);
|
setKimiAnthropicModel(model);
|
||||||
setKimiAnthropicSmallFastModel(smallFastModel);
|
setKimiDefaultHaikuModel(haiku);
|
||||||
|
setKimiDefaultSonnetModel(sonnet);
|
||||||
|
setKimiDefaultOpusModel(opus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [initialData]);
|
}, [initialData]);
|
||||||
@@ -66,21 +79,25 @@ export function useKimiModelSelector({
|
|||||||
// 处理 Kimi 模型变化
|
// 处理 Kimi 模型变化
|
||||||
const handleKimiModelChange = useCallback(
|
const handleKimiModelChange = useCallback(
|
||||||
(
|
(
|
||||||
field: "ANTHROPIC_MODEL" | "ANTHROPIC_SMALL_FAST_MODEL",
|
field:
|
||||||
|
| "ANTHROPIC_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_HAIKU_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_SONNET_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_OPUS_MODEL",
|
||||||
value: string,
|
value: string,
|
||||||
) => {
|
) => {
|
||||||
if (field === "ANTHROPIC_MODEL") {
|
if (field === "ANTHROPIC_MODEL") setKimiAnthropicModel(value);
|
||||||
setKimiAnthropicModel(value);
|
if (field === "ANTHROPIC_DEFAULT_HAIKU_MODEL") setKimiDefaultHaikuModel(value);
|
||||||
} else {
|
if (field === "ANTHROPIC_DEFAULT_SONNET_MODEL") setKimiDefaultSonnetModel(value);
|
||||||
setKimiAnthropicSmallFastModel(value);
|
if (field === "ANTHROPIC_DEFAULT_OPUS_MODEL") setKimiDefaultOpusModel(value);
|
||||||
}
|
|
||||||
|
|
||||||
// 更新配置 JSON
|
// 更新配置 JSON(只写新键并清理旧键)
|
||||||
try {
|
try {
|
||||||
const currentConfig = JSON.parse(settingsConfig || "{}");
|
const currentConfig = JSON.parse(settingsConfig || "{}");
|
||||||
if (!currentConfig.env) currentConfig.env = {};
|
if (!currentConfig.env) currentConfig.env = {};
|
||||||
currentConfig.env[field] = value;
|
if (value.trim()) currentConfig.env[field] = value;
|
||||||
|
else delete currentConfig.env[field];
|
||||||
|
delete currentConfig.env["ANTHROPIC_SMALL_FAST_MODEL"];
|
||||||
const updatedConfigString = JSON.stringify(currentConfig, null, 2);
|
const updatedConfigString = JSON.stringify(currentConfig, null, 2);
|
||||||
onConfigChange(updatedConfigString);
|
onConfigChange(updatedConfigString);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -97,9 +114,16 @@ export function useKimiModelSelector({
|
|||||||
const config = JSON.parse(settingsConfig);
|
const config = JSON.parse(settingsConfig);
|
||||||
if (config.env) {
|
if (config.env) {
|
||||||
const model = config.env.ANTHROPIC_MODEL || "";
|
const model = config.env.ANTHROPIC_MODEL || "";
|
||||||
const smallFastModel = config.env.ANTHROPIC_SMALL_FAST_MODEL || "";
|
const haiku =
|
||||||
|
config.env.ANTHROPIC_DEFAULT_HAIKU_MODEL ||
|
||||||
|
config.env.ANTHROPIC_SMALL_FAST_MODEL ||
|
||||||
|
model || "";
|
||||||
|
const sonnet = config.env.ANTHROPIC_DEFAULT_SONNET_MODEL || model || "";
|
||||||
|
const opus = config.env.ANTHROPIC_DEFAULT_OPUS_MODEL || model || "";
|
||||||
setKimiAnthropicModel(model);
|
setKimiAnthropicModel(model);
|
||||||
setKimiAnthropicSmallFastModel(smallFastModel);
|
setKimiDefaultHaikuModel(haiku);
|
||||||
|
setKimiDefaultSonnetModel(sonnet);
|
||||||
|
setKimiDefaultOpusModel(opus);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
@@ -110,7 +134,9 @@ export function useKimiModelSelector({
|
|||||||
return {
|
return {
|
||||||
shouldShow,
|
shouldShow,
|
||||||
kimiAnthropicModel,
|
kimiAnthropicModel,
|
||||||
kimiAnthropicSmallFastModel,
|
kimiDefaultHaikuModel,
|
||||||
|
kimiDefaultSonnetModel,
|
||||||
|
kimiDefaultOpusModel,
|
||||||
handleKimiModelChange,
|
handleKimiModelChange,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useCallback } from "react";
|
import { useState, useCallback, useEffect } from "react";
|
||||||
|
|
||||||
interface UseModelStateProps {
|
interface UseModelStateProps {
|
||||||
settingsConfig: string;
|
settingsConfig: string;
|
||||||
@@ -9,39 +9,76 @@ interface UseModelStateProps {
|
|||||||
* 管理模型选择状态
|
* 管理模型选择状态
|
||||||
* 支持 ANTHROPIC_MODEL 和 ANTHROPIC_SMALL_FAST_MODEL
|
* 支持 ANTHROPIC_MODEL 和 ANTHROPIC_SMALL_FAST_MODEL
|
||||||
*/
|
*/
|
||||||
export function useModelState({
|
export function useModelState({ settingsConfig, onConfigChange }: UseModelStateProps) {
|
||||||
settingsConfig,
|
|
||||||
onConfigChange,
|
|
||||||
}: UseModelStateProps) {
|
|
||||||
const [claudeModel, setClaudeModel] = useState("");
|
const [claudeModel, setClaudeModel] = useState("");
|
||||||
const [claudeSmallFastModel, setClaudeSmallFastModel] = useState("");
|
const [defaultHaikuModel, setDefaultHaikuModel] = useState("");
|
||||||
|
const [defaultSonnetModel, setDefaultSonnetModel] = useState("");
|
||||||
|
const [defaultOpusModel, setDefaultOpusModel] = useState("");
|
||||||
|
|
||||||
|
// 初始化读取:读新键;若缺失,按兼容优先级回退
|
||||||
|
// Haiku: DEFAULT_HAIKU || SMALL_FAST || MODEL
|
||||||
|
// Sonnet: DEFAULT_SONNET || MODEL || SMALL_FAST
|
||||||
|
// Opus: DEFAULT_OPUS || MODEL || SMALL_FAST
|
||||||
|
// 仅在 settingsConfig 变化时同步一次(表单加载/切换预设时)
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
const cfg = settingsConfig ? JSON.parse(settingsConfig) : {};
|
||||||
|
const env = cfg?.env || {};
|
||||||
|
const model = typeof env.ANTHROPIC_MODEL === "string" ? env.ANTHROPIC_MODEL : "";
|
||||||
|
const small =
|
||||||
|
typeof env.ANTHROPIC_SMALL_FAST_MODEL === "string" ? env.ANTHROPIC_SMALL_FAST_MODEL : "";
|
||||||
|
const haiku =
|
||||||
|
typeof env.ANTHROPIC_DEFAULT_HAIKU_MODEL === "string"
|
||||||
|
? env.ANTHROPIC_DEFAULT_HAIKU_MODEL
|
||||||
|
: small || model;
|
||||||
|
const sonnet =
|
||||||
|
typeof env.ANTHROPIC_DEFAULT_SONNET_MODEL === "string"
|
||||||
|
? env.ANTHROPIC_DEFAULT_SONNET_MODEL
|
||||||
|
: model || small;
|
||||||
|
const opus =
|
||||||
|
typeof env.ANTHROPIC_DEFAULT_OPUS_MODEL === "string"
|
||||||
|
? env.ANTHROPIC_DEFAULT_OPUS_MODEL
|
||||||
|
: model || small;
|
||||||
|
|
||||||
|
setClaudeModel(model || "");
|
||||||
|
setDefaultHaikuModel(haiku || "");
|
||||||
|
setDefaultSonnetModel(sonnet || "");
|
||||||
|
setDefaultOpusModel(opus || "");
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}, [settingsConfig]);
|
||||||
|
|
||||||
const handleModelChange = useCallback(
|
const handleModelChange = useCallback(
|
||||||
(
|
(
|
||||||
field: "ANTHROPIC_MODEL" | "ANTHROPIC_SMALL_FAST_MODEL",
|
field:
|
||||||
|
| "ANTHROPIC_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_HAIKU_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_SONNET_MODEL"
|
||||||
|
| "ANTHROPIC_DEFAULT_OPUS_MODEL",
|
||||||
value: string,
|
value: string,
|
||||||
) => {
|
) => {
|
||||||
if (field === "ANTHROPIC_MODEL") {
|
if (field === "ANTHROPIC_MODEL") setClaudeModel(value);
|
||||||
setClaudeModel(value);
|
if (field === "ANTHROPIC_DEFAULT_HAIKU_MODEL") setDefaultHaikuModel(value);
|
||||||
} else {
|
if (field === "ANTHROPIC_DEFAULT_SONNET_MODEL") setDefaultSonnetModel(value);
|
||||||
setClaudeSmallFastModel(value);
|
if (field === "ANTHROPIC_DEFAULT_OPUS_MODEL") setDefaultOpusModel(value);
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const currentConfig = settingsConfig
|
const currentConfig = settingsConfig ? JSON.parse(settingsConfig) : { env: {} };
|
||||||
? JSON.parse(settingsConfig)
|
|
||||||
: { env: {} };
|
|
||||||
if (!currentConfig.env) currentConfig.env = {};
|
if (!currentConfig.env) currentConfig.env = {};
|
||||||
|
|
||||||
if (value.trim()) {
|
// 新键仅写入;旧键不再写入
|
||||||
currentConfig.env[field] = value.trim();
|
const trimmed = value.trim();
|
||||||
|
if (trimmed) {
|
||||||
|
currentConfig.env[field] = trimmed;
|
||||||
} else {
|
} else {
|
||||||
delete currentConfig.env[field];
|
delete currentConfig.env[field];
|
||||||
}
|
}
|
||||||
|
// 删除旧键
|
||||||
|
delete currentConfig.env["ANTHROPIC_SMALL_FAST_MODEL"];
|
||||||
|
|
||||||
onConfigChange(JSON.stringify(currentConfig, null, 2));
|
onConfigChange(JSON.stringify(currentConfig, null, 2));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// 如果 JSON 解析失败,不做处理
|
|
||||||
console.error("Failed to update model config:", err);
|
console.error("Failed to update model config:", err);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -51,8 +88,12 @@ export function useModelState({
|
|||||||
return {
|
return {
|
||||||
claudeModel,
|
claudeModel,
|
||||||
setClaudeModel,
|
setClaudeModel,
|
||||||
claudeSmallFastModel,
|
defaultHaikuModel,
|
||||||
setClaudeSmallFastModel,
|
setDefaultHaikuModel,
|
||||||
|
defaultSonnetModel,
|
||||||
|
setDefaultSonnetModel,
|
||||||
|
defaultOpusModel,
|
||||||
|
setDefaultOpusModel,
|
||||||
handleModelChange,
|
handleModelChange,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ export const providerPresets: ProviderPreset[] = [
|
|||||||
ANTHROPIC_BASE_URL: "https://api.deepseek.com/anthropic",
|
ANTHROPIC_BASE_URL: "https://api.deepseek.com/anthropic",
|
||||||
ANTHROPIC_AUTH_TOKEN: "",
|
ANTHROPIC_AUTH_TOKEN: "",
|
||||||
ANTHROPIC_MODEL: "DeepSeek-V3.2-Exp",
|
ANTHROPIC_MODEL: "DeepSeek-V3.2-Exp",
|
||||||
ANTHROPIC_SMALL_FAST_MODEL: "DeepSeek-V3.2-Exp",
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: "DeepSeek-V3.2-Exp",
|
||||||
|
ANTHROPIC_DEFAULT_SONNET_MODEL: "DeepSeek-V3.2-Exp",
|
||||||
|
ANTHROPIC_DEFAULT_OPUS_MODEL: "DeepSeek-V3.2-Exp",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
category: "cn_official",
|
category: "cn_official",
|
||||||
@@ -75,7 +77,6 @@ export const providerPresets: ProviderPreset[] = [
|
|||||||
ANTHROPIC_AUTH_TOKEN: "",
|
ANTHROPIC_AUTH_TOKEN: "",
|
||||||
// 兼容旧键名,保持前端读取一致
|
// 兼容旧键名,保持前端读取一致
|
||||||
ANTHROPIC_MODEL: "GLM-4.6",
|
ANTHROPIC_MODEL: "GLM-4.6",
|
||||||
ANTHROPIC_SMALL_FAST_MODEL: "glm-4.5-air",
|
|
||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL: "glm-4.5-air",
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: "glm-4.5-air",
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-4.6",
|
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-4.6",
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-4.6",
|
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-4.6",
|
||||||
@@ -92,7 +93,9 @@ export const providerPresets: ProviderPreset[] = [
|
|||||||
"https://dashscope.aliyuncs.com/api/v2/apps/claude-code-proxy",
|
"https://dashscope.aliyuncs.com/api/v2/apps/claude-code-proxy",
|
||||||
ANTHROPIC_AUTH_TOKEN: "",
|
ANTHROPIC_AUTH_TOKEN: "",
|
||||||
ANTHROPIC_MODEL: "qwen3-max",
|
ANTHROPIC_MODEL: "qwen3-max",
|
||||||
ANTHROPIC_SMALL_FAST_MODEL: "qwen3-max",
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: "qwen3-max",
|
||||||
|
ANTHROPIC_DEFAULT_SONNET_MODEL: "qwen3-max",
|
||||||
|
ANTHROPIC_DEFAULT_OPUS_MODEL: "qwen3-max",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
category: "cn_official",
|
category: "cn_official",
|
||||||
@@ -105,7 +108,9 @@ export const providerPresets: ProviderPreset[] = [
|
|||||||
ANTHROPIC_BASE_URL: "https://api.moonshot.cn/anthropic",
|
ANTHROPIC_BASE_URL: "https://api.moonshot.cn/anthropic",
|
||||||
ANTHROPIC_AUTH_TOKEN: "",
|
ANTHROPIC_AUTH_TOKEN: "",
|
||||||
ANTHROPIC_MODEL: "kimi-k2-turbo-preview",
|
ANTHROPIC_MODEL: "kimi-k2-turbo-preview",
|
||||||
ANTHROPIC_SMALL_FAST_MODEL: "kimi-k2-turbo-preview",
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: "kimi-k2-turbo-preview",
|
||||||
|
ANTHROPIC_DEFAULT_SONNET_MODEL: "kimi-k2-turbo-preview",
|
||||||
|
ANTHROPIC_DEFAULT_OPUS_MODEL: "kimi-k2-turbo-preview",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
category: "cn_official",
|
category: "cn_official",
|
||||||
@@ -118,7 +123,9 @@ export const providerPresets: ProviderPreset[] = [
|
|||||||
ANTHROPIC_BASE_URL: "https://api-inference.modelscope.cn",
|
ANTHROPIC_BASE_URL: "https://api-inference.modelscope.cn",
|
||||||
ANTHROPIC_AUTH_TOKEN: "",
|
ANTHROPIC_AUTH_TOKEN: "",
|
||||||
ANTHROPIC_MODEL: "ZhipuAI/GLM-4.6",
|
ANTHROPIC_MODEL: "ZhipuAI/GLM-4.6",
|
||||||
ANTHROPIC_SMALL_FAST_MODEL: "ZhipuAI/GLM-4.6",
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: "ZhipuAI/GLM-4.6",
|
||||||
|
ANTHROPIC_DEFAULT_SONNET_MODEL: "ZhipuAI/GLM-4.6",
|
||||||
|
ANTHROPIC_DEFAULT_OPUS_MODEL: "ZhipuAI/GLM-4.6",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
category: "aggregator",
|
category: "aggregator",
|
||||||
@@ -133,7 +140,9 @@ export const providerPresets: ProviderPreset[] = [
|
|||||||
"https://vanchin.streamlake.ai/api/gateway/v1/endpoints/${ENDPOINT_ID}/claude-code-proxy",
|
"https://vanchin.streamlake.ai/api/gateway/v1/endpoints/${ENDPOINT_ID}/claude-code-proxy",
|
||||||
ANTHROPIC_AUTH_TOKEN: "",
|
ANTHROPIC_AUTH_TOKEN: "",
|
||||||
ANTHROPIC_MODEL: "KAT-Coder",
|
ANTHROPIC_MODEL: "KAT-Coder",
|
||||||
ANTHROPIC_SMALL_FAST_MODEL: "KAT-Coder",
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: "KAT-Coder",
|
||||||
|
ANTHROPIC_DEFAULT_SONNET_MODEL: "KAT-Coder",
|
||||||
|
ANTHROPIC_DEFAULT_OPUS_MODEL: "KAT-Coder",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
category: "cn_official",
|
category: "cn_official",
|
||||||
@@ -155,7 +164,7 @@ export const providerPresets: ProviderPreset[] = [
|
|||||||
ANTHROPIC_BASE_URL: "https://api.longcat.chat/anthropic",
|
ANTHROPIC_BASE_URL: "https://api.longcat.chat/anthropic",
|
||||||
ANTHROPIC_AUTH_TOKEN: "",
|
ANTHROPIC_AUTH_TOKEN: "",
|
||||||
ANTHROPIC_MODEL: "LongCat-Flash-Chat",
|
ANTHROPIC_MODEL: "LongCat-Flash-Chat",
|
||||||
ANTHROPIC_SMALL_FAST_MODEL: "LongCat-Flash-Chat",
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: "LongCat-Flash-Chat",
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL: "LongCat-Flash-Chat",
|
ANTHROPIC_DEFAULT_SONNET_MODEL: "LongCat-Flash-Chat",
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL: "LongCat-Flash-Chat",
|
ANTHROPIC_DEFAULT_OPUS_MODEL: "LongCat-Flash-Chat",
|
||||||
CLAUDE_CODE_MAX_OUTPUT_TOKENS: "6000",
|
CLAUDE_CODE_MAX_OUTPUT_TOKENS: "6000",
|
||||||
|
|||||||
@@ -258,6 +258,9 @@
|
|||||||
"visitWebsite": "Visit {{url}}",
|
"visitWebsite": "Visit {{url}}",
|
||||||
"anthropicModel": "Main Model",
|
"anthropicModel": "Main Model",
|
||||||
"anthropicSmallFastModel": "Fast Model",
|
"anthropicSmallFastModel": "Fast Model",
|
||||||
|
"anthropicDefaultHaikuModel": "Default Haiku Model",
|
||||||
|
"anthropicDefaultSonnetModel": "Default Sonnet Model",
|
||||||
|
"anthropicDefaultOpusModel": "Default Opus Model",
|
||||||
"modelPlaceholder": "GLM-4.6",
|
"modelPlaceholder": "GLM-4.6",
|
||||||
"smallModelPlaceholder": "GLM-4.5-Air",
|
"smallModelPlaceholder": "GLM-4.5-Air",
|
||||||
"modelHelper": "Optional: Specify default Claude model to use, leave blank to use system default.",
|
"modelHelper": "Optional: Specify default Claude model to use, leave blank to use system default.",
|
||||||
@@ -373,6 +376,9 @@
|
|||||||
"modelConfig": "Model Configuration",
|
"modelConfig": "Model Configuration",
|
||||||
"mainModel": "Main Model",
|
"mainModel": "Main Model",
|
||||||
"fastModel": "Fast Model",
|
"fastModel": "Fast Model",
|
||||||
|
"haikuModel": "Default Haiku",
|
||||||
|
"sonnetModel": "Default Sonnet",
|
||||||
|
"opusModel": "Default Opus",
|
||||||
"refreshModels": "Refresh Model List",
|
"refreshModels": "Refresh Model List",
|
||||||
"pleaseSelectModel": "Please select a model",
|
"pleaseSelectModel": "Please select a model",
|
||||||
"noModels": "No models available",
|
"noModels": "No models available",
|
||||||
|
|||||||
@@ -258,6 +258,9 @@
|
|||||||
"visitWebsite": "访问 {{url}}",
|
"visitWebsite": "访问 {{url}}",
|
||||||
"anthropicModel": "主模型",
|
"anthropicModel": "主模型",
|
||||||
"anthropicSmallFastModel": "快速模型",
|
"anthropicSmallFastModel": "快速模型",
|
||||||
|
"anthropicDefaultHaikuModel": "Haiku 默认模型",
|
||||||
|
"anthropicDefaultSonnetModel": "Sonnet 默认模型",
|
||||||
|
"anthropicDefaultOpusModel": "Opus 默认模型",
|
||||||
"modelPlaceholder": "GLM-4.6",
|
"modelPlaceholder": "GLM-4.6",
|
||||||
"smallModelPlaceholder": "GLM-4.5-Air",
|
"smallModelPlaceholder": "GLM-4.5-Air",
|
||||||
"modelHelper": "可选:指定默认使用的 Claude 模型,留空则使用系统默认。",
|
"modelHelper": "可选:指定默认使用的 Claude 模型,留空则使用系统默认。",
|
||||||
@@ -373,6 +376,9 @@
|
|||||||
"modelConfig": "模型配置",
|
"modelConfig": "模型配置",
|
||||||
"mainModel": "主模型",
|
"mainModel": "主模型",
|
||||||
"fastModel": "快速模型",
|
"fastModel": "快速模型",
|
||||||
|
"haikuModel": "Haiku 默认",
|
||||||
|
"sonnetModel": "Sonnet 默认",
|
||||||
|
"opusModel": "Opus 默认",
|
||||||
"refreshModels": "刷新模型列表",
|
"refreshModels": "刷新模型列表",
|
||||||
"pleaseSelectModel": "请选择模型",
|
"pleaseSelectModel": "请选择模型",
|
||||||
"noModels": "暂无模型",
|
"noModels": "暂无模型",
|
||||||
|
|||||||
Reference in New Issue
Block a user