mirror of
https://github.com/zhouxiaoka/autoclip.git
synced 2026-10-02 02:34:34 +08:00
feat(settings): 模型设置新增赞助合作伙伴 Infistar 无限星河预设
- 后端 cloud_presets 新增 infistar:预设 https://infistar.cc/v1,独立 infistar_api_key (含 INFISTAR_API_KEY 环境变量);CLI / MCP 支持 --provider infistar。 - 多模型网关不内置型号名单、不预设默认模型:填好 Key 后从 /v1/models 拉取, 选中的 gpt / deepseek / gemini 等型号不会被当成「别家型号」重置。 - 设置页选 Infistar 时显示「注册并领取体验额度」「接入说明」,并注明含推广分成; 新增 sponsor_link_opened 事件(只记录入口,不含个人信息)。八语文案同步。 - 接入说明补充新版一步选择的流程,保留旧版手动填写方式。 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,9 @@
|
||||
|
||||
## [未发布]
|
||||
|
||||
### 新增
|
||||
- 模型设置新增赞助合作伙伴「Infistar 无限星河」:接口地址已预设,填好 Key 后自动列出账号可用的模型;设置页提供专属注册链接(可领 $5 体验额度)和接入说明。CLI / MCP 支持 `--provider infistar` 与 `INFISTAR_API_KEY`。
|
||||
|
||||
### 修复
|
||||
- 时间线重试只使用本次有效结果,避免失败后误用上次候选;原始响应缓存现在会正常解析,无效缓存不会自动触发模型请求。
|
||||
- 智能导入后台任务提交失败后可明确重试,已有方案、草稿和成片保留;修改方案失败时同步恢复偏好。
|
||||
|
||||
@@ -58,6 +58,7 @@ class ApiKeys(BaseModel):
|
||||
kimi: str = Field(default="", description="Kimi / 月之暗面 API密钥")
|
||||
glm: str = Field(default="", description="智谱 GLM API密钥")
|
||||
grok: str = Field(default="", description="xAI Grok API密钥")
|
||||
infistar: str = Field(default="", description="Infistar 无限星河 API密钥")
|
||||
seed: str = Field(default="", description="火山方舟 Seed / 豆包 API密钥")
|
||||
jimeng_access: str = Field(default="", description="即梦AI访问密钥")
|
||||
jimeng_secret: str = Field(default="", description="即梦AI秘密密钥")
|
||||
@@ -66,7 +67,7 @@ class ApiKeys(BaseModel):
|
||||
class ApiSettings(BaseModel):
|
||||
"""API设置"""
|
||||
api_keys: ApiKeys = Field(default_factory=ApiKeys, description="API密钥")
|
||||
api_provider: str = Field(default="dashscope", description="当前 LLM 提供商(dashscope / openai / gemini / deepseek / seed / kimi / glm / grok,或本地预设 ollama / lmstudio)")
|
||||
api_provider: str = Field(default="dashscope", description="当前 LLM 提供商(dashscope / openai / gemini / deepseek / seed / kimi / glm / grok / infistar,或本地预设 ollama / lmstudio)")
|
||||
api_base_url: str = Field(default="", description="OpenAI 兼容接口地址;provider=openai 时空为官方地址,本地预设为空时用预设默认地址")
|
||||
api_model: str = Field(default="qwen-plus", description="默认模型")
|
||||
api_max_tokens: int = Field(default=4096, description="最大Token数")
|
||||
@@ -258,6 +259,7 @@ async def get_settings():
|
||||
kimi="",
|
||||
glm="",
|
||||
grok="",
|
||||
infistar="",
|
||||
seed="",
|
||||
jimeng_access="", # 默认值
|
||||
jimeng_secret="" # 默认值
|
||||
@@ -692,6 +694,7 @@ def _saved_provider_api_key(settings: DesktopSettings, provider: str) -> str:
|
||||
"kimi": keys.kimi,
|
||||
"glm": keys.glm,
|
||||
"grok": keys.grok,
|
||||
"infistar": keys.infistar,
|
||||
"seed": keys.seed,
|
||||
}.get((provider or "").strip().lower(), "") or ""
|
||||
|
||||
|
||||
+2
-1
@@ -59,7 +59,7 @@ def _err(msg: str) -> None:
|
||||
|
||||
def _add_llm_args(p: argparse.ArgumentParser) -> None:
|
||||
g = p.add_argument_group("模型(不填则用桌面应用设置页里的配置)")
|
||||
g.add_argument("--provider", choices=PROVIDER_CHOICES, help="dashscope / openai / gemini / deepseek / seed / kimi / glm / grok,或本地预设 ollama / lmstudio")
|
||||
g.add_argument("--provider", choices=PROVIDER_CHOICES, help="dashscope / openai / gemini / deepseek / seed / kimi / glm / grok / infistar,或本地预设 ollama / lmstudio")
|
||||
g.add_argument("--model", help="模型名,如 qwen-plus、gpt-4o-mini、qwen2.5:7b")
|
||||
g.add_argument("--base-url", help="OpenAI 兼容接口地址(provider=openai 时用;ollama/lmstudio 有默认值)")
|
||||
g.add_argument("--api-key", help="API Key(本地模型可不填)。也可用环境变量 AUTOCLIP_API_KEY")
|
||||
@@ -206,6 +206,7 @@ def cmd_providers(args: argparse.Namespace) -> int:
|
||||
("kimi", "Kimi(月之暗面)", "需要 key;国内直连"),
|
||||
("glm", "智谱 GLM", "需要 key;国内直连"),
|
||||
("grok", "Grok(xAI)", "需要 key"),
|
||||
("infistar", "Infistar 无限星河(赞助)", "需要 key,专属链接注册可领体验额度"),
|
||||
] + [
|
||||
(p.key, p.display_name, f"无需 key;默认 {p.base_url}" + (f",默认模型 {p.default_model}" if p.default_model else ""))
|
||||
for p in LOCAL_PRESETS.values()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
云端 OpenAI 兼容预设:DeepSeek / Seed / Kimi / GLM / Grok。
|
||||
云端 OpenAI 兼容预设:DeepSeek / Seed / Kimi / GLM / Grok / Infistar(赞助)。
|
||||
|
||||
底层仍是 openai + 官方 base_url,和 Ollama 预设同一套路,但必须带各家自己的 key,
|
||||
不能复用用户的 OpenAI key。设置页、CLI、MCP 都用 `--provider deepseek` 这种名字。
|
||||
@@ -67,6 +67,17 @@ CLOUD_PRESETS: Dict[str, CloudPreset] = {
|
||||
docs_url="https://console.x.ai",
|
||||
hint="xAI Grok。需要 xAI 账号。",
|
||||
),
|
||||
# 赞助合作伙伴。多模型网关,可用型号随账号而定,所以不预设默认模型,填好 key 后从 /v1/models 拉取。
|
||||
# docs_url 是 AutoClip 专属注册链接(新用户可领体验额度),说明见 docs/INFISTAR_SETUP.md。
|
||||
"infistar": CloudPreset(
|
||||
key="infistar",
|
||||
display_name="Infistar 无限星河",
|
||||
base_url="https://infistar.cc/v1",
|
||||
default_model="",
|
||||
api_key_setting="infistar_api_key",
|
||||
docs_url="https://www.infistar.cc/register?aff=XLK3BCM6&ref_source=link",
|
||||
hint="赞助合作伙伴。一个 Key 调 Claude / GPT / Gemini / DeepSeek 等模型,专属链接注册可领体验额度。",
|
||||
),
|
||||
}
|
||||
|
||||
_ALIASES = {
|
||||
@@ -84,6 +95,8 @@ _ALIASES = {
|
||||
"ark": "seed",
|
||||
"bytedance": "seed",
|
||||
"volces": "seed",
|
||||
"infistar.cc": "infistar",
|
||||
"wuxianxinghe": "infistar",
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +110,7 @@ def normalize_cloud_preset_key(name: Optional[str]) -> Optional[str]:
|
||||
|
||||
def resolve_cloud_preset(provider: Optional[str], base_url: Optional[str] = None) -> Optional[Tuple[str, str, CloudPreset]]:
|
||||
"""
|
||||
若 provider 是 deepseek / seed / kimi / glm / grok(或别名),返回 (openai, base_url, preset)。
|
||||
若 provider 是 deepseek / seed / kimi / glm / grok / infistar(或别名),返回 (openai, base_url, preset)。
|
||||
不是云端预设则返回 None。
|
||||
"""
|
||||
key = normalize_cloud_preset_key(provider)
|
||||
|
||||
@@ -101,6 +101,7 @@ class LLMManager:
|
||||
"kimi_api_key": "",
|
||||
"glm_api_key": "",
|
||||
"grok_api_key": "",
|
||||
"infistar_api_key": "",
|
||||
"seed_api_key": "",
|
||||
"model_name": "qwen-plus",
|
||||
"chunk_size": 5000,
|
||||
@@ -127,6 +128,7 @@ class LLMManager:
|
||||
"kimi_api_key": api_keys.get("kimi", ""),
|
||||
"glm_api_key": api_keys.get("glm", ""),
|
||||
"grok_api_key": api_keys.get("grok", ""),
|
||||
"infistar_api_key": api_keys.get("infistar", ""),
|
||||
"seed_api_key": api_keys.get("seed", ""),
|
||||
"model_name": api.get("api_model", "qwen-plus")
|
||||
})
|
||||
@@ -173,7 +175,7 @@ class LLMManager:
|
||||
settings["model_name"] = default_model
|
||||
|
||||
def _apply_cloud_preset(self, settings: Dict[str, Any]) -> None:
|
||||
"""deepseek / seed / kimi / glm / grok → openai + 官方地址,用各家自己的 key。"""
|
||||
"""deepseek / seed / kimi / glm / grok / infistar → openai + 官方地址,用各家自己的 key。"""
|
||||
from backend.core.cloud_presets import resolve_cloud_preset
|
||||
from backend.core.model_catalog import curated_models, default_model_for
|
||||
|
||||
@@ -186,8 +188,14 @@ class LLMManager:
|
||||
settings["cloud_preset"] = preset.key
|
||||
settings["openai_base_url"] = base_url
|
||||
current = (settings.get("model_name") or "").strip()
|
||||
own = curated_models(preset.key)
|
||||
if not own:
|
||||
# 多模型网关(infistar):gpt / deepseek / gemini 都是合法型号,用户选什么就用什么
|
||||
if not current and preset.default_model:
|
||||
settings["model_name"] = preset.default_model
|
||||
return
|
||||
known = set(curated_models())
|
||||
if not current or current == "qwen-plus" or (current in known and current not in curated_models(preset.key)):
|
||||
if not current or current == "qwen-plus" or (current in known and current not in own):
|
||||
settings["model_name"] = preset.default_model or default_model_for(preset.key)
|
||||
|
||||
# Docker / 本地脚本模式没有设置页可用,只能靠环境变量(env.example 里也是这么写的),
|
||||
@@ -201,6 +209,7 @@ class LLMManager:
|
||||
"kimi_api_key": ("API_KIMI_API_KEY", "MOONSHOT_API_KEY", "KIMI_API_KEY"),
|
||||
"glm_api_key": ("API_GLM_API_KEY", "ZHIPU_API_KEY", "GLM_API_KEY"),
|
||||
"grok_api_key": ("API_GROK_API_KEY", "XAI_API_KEY", "GROK_API_KEY"),
|
||||
"infistar_api_key": ("API_INFISTAR_API_KEY", "INFISTAR_API_KEY"),
|
||||
"seed_api_key": ("API_SEED_API_KEY", "ARK_API_KEY", "VOLCENGINE_API_KEY", "DOUBAO_API_KEY"),
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,8 @@ CURATED_MODELS: Dict[str, List[str]] = {
|
||||
"grok-4.5",
|
||||
"grok-4.3",
|
||||
],
|
||||
# 多模型网关,型号随账号而定:不内置名单,填好 key 后实时拉取
|
||||
"infistar": [],
|
||||
}
|
||||
|
||||
DEFAULT_MODELS: Dict[str, str] = {
|
||||
@@ -85,6 +87,7 @@ DEFAULT_MODELS: Dict[str, str] = {
|
||||
"kimi": "kimi-k2.6",
|
||||
"glm": "glm-5.3",
|
||||
"grok": "grok-4.6",
|
||||
"infistar": "",
|
||||
}
|
||||
|
||||
PROVIDER_LABELS: Dict[str, str] = {
|
||||
@@ -96,6 +99,7 @@ PROVIDER_LABELS: Dict[str, str] = {
|
||||
"kimi": "Kimi",
|
||||
"glm": "GLM",
|
||||
"grok": "Grok",
|
||||
"infistar": "Infistar",
|
||||
}
|
||||
|
||||
CLOUD_PROVIDERS = frozenset(CURATED_MODELS)
|
||||
@@ -386,7 +390,8 @@ async def list_available_models(
|
||||
source="catalog",
|
||||
reachable=False,
|
||||
default_model=default_model_for(key),
|
||||
models=curated or curated_models("dashscope"),
|
||||
# 已知提供商内置名单为空(如 infistar)时保持为空,别拿通义的型号冒充
|
||||
models=curated if key in CURATED_MODELS else curated_models("dashscope"),
|
||||
catalog=catalog,
|
||||
)
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ def _make_override(provider: Optional[str], model: Optional[str], base_url: Opti
|
||||
description=(
|
||||
"把一条本地视频切成高光片段(同步,耗时数分钟到数十分钟,期间会发进度)。"
|
||||
"返回切片列表(标题 / 起止时间 / 评分 / mp4 路径)与合集。"
|
||||
"provider 可选 dashscope / openai / gemini / deepseek / seed / kimi / glm / grok / ollama / lmstudio;不填用桌面应用里已配置的模型。"
|
||||
"provider 可选 dashscope / openai / gemini / deepseek / seed / kimi / glm / grok / infistar / ollama / lmstudio;不填用桌面应用里已配置的模型。"
|
||||
),
|
||||
)
|
||||
async def clip_video(
|
||||
@@ -220,7 +220,7 @@ def list_providers() -> Dict[str, Any]:
|
||||
|
||||
return {
|
||||
"current": get_llm_manager().get_current_provider_info(),
|
||||
"cloud": ["dashscope", "openai", "gemini", "deepseek", "seed", "kimi", "glm", "grok"],
|
||||
"cloud": ["dashscope", "openai", "gemini", "deepseek", "seed", "kimi", "glm", "grok", "infistar"],
|
||||
"local_presets": presets_as_dicts(),
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ from typing import Any, Callable, Dict, List, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
PROVIDER_CHOICES = ("dashscope", "openai", "gemini", "deepseek", "seed", "kimi", "glm", "grok", "ollama", "lmstudio")
|
||||
PROVIDER_CHOICES = ("dashscope", "openai", "gemini", "deepseek", "seed", "kimi", "glm", "grok", "infistar", "ollama", "lmstudio")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- environment ---
|
||||
@@ -145,7 +145,7 @@ def configure_llm(override: LLMOverride) -> Dict[str, Any]:
|
||||
"dashscope": "dashscope_api_key", "openai": "openai_api_key",
|
||||
"gemini": "gemini_api_key", "siliconflow": "siliconflow_api_key",
|
||||
"deepseek": "deepseek_api_key",
|
||||
"kimi": "kimi_api_key", "glm": "glm_api_key", "grok": "grok_api_key",
|
||||
"kimi": "kimi_api_key", "glm": "glm_api_key", "grok": "grok_api_key", "infistar": "infistar_api_key",
|
||||
"seed": "seed_api_key",
|
||||
}.get(provider)
|
||||
if key_field:
|
||||
|
||||
@@ -31,7 +31,7 @@ def fake_openai(monkeypatch):
|
||||
monkeypatch.setitem(sys.modules, "openai", module)
|
||||
_FakeOpenAIClient.created.clear()
|
||||
monkeypatch.delenv("OPENAI_BASE_URL", raising=False)
|
||||
for name in ("LLM_PROVIDER", "API_MODEL_NAME", "LLM_MODEL", "API_OPENAI_API_KEY", "OPENAI_API_KEY", "API_DEEPSEEK_API_KEY", "DEEPSEEK_API_KEY"):
|
||||
for name in ("LLM_PROVIDER", "API_MODEL_NAME", "LLM_MODEL", "API_OPENAI_API_KEY", "OPENAI_API_KEY", "API_DEEPSEEK_API_KEY", "DEEPSEEK_API_KEY", "API_INFISTAR_API_KEY", "INFISTAR_API_KEY"):
|
||||
monkeypatch.delenv(name, raising=False)
|
||||
from backend.core import llm_manager as manager_module
|
||||
monkeypatch.setattr(manager_module.config_sync_service, "is_sync_needed", lambda: False)
|
||||
@@ -89,4 +89,34 @@ def test_manager_uses_seed_ark_key_not_openai(fake_openai, tmp_path):
|
||||
|
||||
def test_curated_lists_drop_retired_aliases():
|
||||
assert "gpt-4o" not in CLOUD_PRESETS
|
||||
assert set(CLOUD_PRESETS) == {"deepseek", "seed", "kimi", "glm", "grok"}
|
||||
assert set(CLOUD_PRESETS) == {"deepseek", "seed", "kimi", "glm", "grok", "infistar"}
|
||||
|
||||
|
||||
def test_infistar_sponsor_preset_uses_gateway_and_own_key(fake_openai, tmp_path):
|
||||
provider, url, preset = resolve_cloud_preset("infistar")
|
||||
assert provider == "openai"
|
||||
assert url == "https://infistar.cc/v1"
|
||||
# 多模型网关不预设型号;专属注册链接带推广参数
|
||||
assert preset.default_model == ""
|
||||
assert "aff=" in preset.docs_url
|
||||
|
||||
settings = tmp_path / "settings.json"
|
||||
settings.write_text(
|
||||
'{"api": {"api_keys": {"openai": "sk-openai-should-not-be-used", "infistar": "sk-infistar-key-123"}, '
|
||||
'"api_provider": "infistar", "api_model": "deepseek-v4-pro"}}',
|
||||
encoding="utf-8",
|
||||
)
|
||||
info = LLMManager(settings_file=settings).get_current_provider_info()
|
||||
assert info["provider"] == "infistar"
|
||||
assert info["base_url"] == "https://infistar.cc/v1"
|
||||
assert info["model"] == "deepseek-v4-pro"
|
||||
assert fake_openai.created[-1]["api_key"] == "sk-infistar-key-123"
|
||||
assert fake_openai.created[-1]["base_url"] == "https://infistar.cc/v1"
|
||||
|
||||
|
||||
def test_infistar_key_from_env(fake_openai, tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("INFISTAR_API_KEY", "sk-infistar-from-env")
|
||||
settings = tmp_path / "settings.json"
|
||||
settings.write_text('{"api": {"api_keys": {}, "api_provider": "infistar", "api_model": "gpt-5-mini"}}', encoding="utf-8")
|
||||
LLMManager(settings_file=settings).get_current_provider_info()
|
||||
assert fake_openai.created[-1]["api_key"] == "sk-infistar-from-env"
|
||||
|
||||
@@ -225,3 +225,24 @@ def test_provider_catalog_infos_follow_curated_list():
|
||||
assert names == model_catalog.curated_models("dashscope")
|
||||
openai_names = [m.name for m in _catalog_model_infos(ProviderType.OPENAI)]
|
||||
assert "gpt-5" in openai_names
|
||||
|
||||
|
||||
def test_infistar_has_no_builtin_list_and_fetches_gateway_models(monkeypatch):
|
||||
# 没 key:不拿通义的型号冒充
|
||||
empty = asyncio.run(model_catalog.list_available_models("infistar"))
|
||||
assert empty.models == [] and empty.default_model == "" and empty.source == "catalog"
|
||||
|
||||
_FakeAsyncClient.calls = []
|
||||
_FakeAsyncClient.routes = {
|
||||
"https://infistar.cc/v1/models": (
|
||||
{"data": [{"id": "claude-sonnet-5-5"}, {"id": "deepseek-v4-pro"}, {"id": "gemini-3.8-flash"},
|
||||
{"id": "text-embedding-3-large"}, {"id": "sora-2"}]},
|
||||
200,
|
||||
)
|
||||
}
|
||||
import httpx
|
||||
monkeypatch.setattr(httpx, "AsyncClient", _FakeAsyncClient)
|
||||
live = asyncio.run(model_catalog.list_available_models("infistar", api_key="sk-infistar-key-123", refresh=True))
|
||||
assert live.source == "live"
|
||||
# 网关里各家型号都保留,只去掉嵌入 / 视频
|
||||
assert live.models == ["claude-sonnet-5-5", "deepseek-v4-pro", "gemini-3.8-flash"]
|
||||
|
||||
@@ -10,6 +10,17 @@ Register through the [AutoClip referral link](https://www.infistar.cc/register?a
|
||||
|
||||
## Configure AutoClip
|
||||
|
||||
### Version 1.4.1 and later: pick Infistar directly
|
||||
|
||||
1. Open Settings → Model and choose **Infistar**. The base URL `https://infistar.cc/v1` is preset.
|
||||
2. No account yet? Click "Sign up & claim credit" to register through the referral link, then create an API key in the console.
|
||||
3. Paste the key. The model list fills in with the models available to your account; pick one.
|
||||
4. Test the connection and save.
|
||||
|
||||
CLI / MCP: `autoclip run video.mp4 --provider infistar --api-key sk-… --model <model id>`, or set `INFISTAR_API_KEY`.
|
||||
|
||||
### Older versions: configure as an OpenAI-compatible API
|
||||
|
||||
Open Settings → Model and enter:
|
||||
|
||||
| Field | Value |
|
||||
|
||||
+12
-1
@@ -10,6 +10,17 @@ Infistar 是 AutoClip 的赞助合作伙伴,可通过现有 OpenAI 兼容接
|
||||
|
||||
## 配置 AutoClip
|
||||
|
||||
### 新版本(1.4.1 起):直接选择 Infistar
|
||||
|
||||
1. 打开「设置 → 模型」,提供商选 **Infistar**。接口地址已预设为 `https://infistar.cc/v1`,不用填。
|
||||
2. 还没有账号时,点「注册并领取体验额度」,用专属链接注册并在控制台创建 API Key。
|
||||
3. 把 API Key 粘贴进来。模型下拉会自动列出这个账号可用的型号,选一个。
|
||||
4. 点「测试连接」,再保存。
|
||||
|
||||
命令行 / MCP:`autoclip run video.mp4 --provider infistar --api-key sk-… --model <模型 ID>`,也可以设置环境变量 `INFISTAR_API_KEY`。
|
||||
|
||||
### 旧版本:用 OpenAI 兼容接口手动填写
|
||||
|
||||
打开「设置 → 模型」,填写以下内容:
|
||||
|
||||
| 配置项 | 内容 |
|
||||
@@ -19,7 +30,7 @@ Infistar 是 AutoClip 的赞助合作伙伴,可通过现有 OpenAI 兼容接
|
||||
| API Key | 你在 Infistar 创建的 API Key |
|
||||
| 模型 | 当前账号可用、支持 Chat Completions 的真实模型 ID |
|
||||
|
||||
接口地址中的 `/v1` 只填写一次,不要追加 `/chat/completions`。国际网络也可使用 `https://infistar.ai/v1`,参见 [Infistar 网关配置文档](https://doc.infistar.cc/integration-guides/gateway-config)。
|
||||
接口地址中的 `/v1` 只填写一次,不要追加 `/chat/completions`。国际网络也可使用 `https://infistar.ai/v1`(新版本选 OpenAI 兼容接口手动填写即可),参见 [Infistar 网关配置文档](https://doc.infistar.cc/integration-guides/gateway-config)。
|
||||
|
||||
从模型列表选择或手动输入真实模型 ID,执行「测试连接」并保存。不要直接沿用 OpenAI 官方默认模型名,具体可用型号由 Infistar 账号权限和模型目录决定。
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ API_DASHSCOPE_API_KEY=your_dashscope_api_key_here
|
||||
# API_KIMI_API_KEY=
|
||||
# API_GLM_API_KEY=
|
||||
# API_GROK_API_KEY=
|
||||
# API_INFISTAR_API_KEY=
|
||||
# OpenAI 兼容接口地址(LLM_PROVIDER=openai 时生效,留空走 OpenAI 官方)。
|
||||
# 智谱: https://open.bigmodel.cn/api/paas/v4 DeepSeek: https://api.deepseek.com/v1
|
||||
# Seed / 火山方舟: https://ark.cn-beijing.volces.com/api/v3
|
||||
|
||||
@@ -15,6 +15,8 @@ export const AnalyticsEvent = {
|
||||
ProcessingFailed: 'processing_failed',
|
||||
/** 设置/更新 LLM API key */
|
||||
ApiKeyConfigured: 'api_key_configured',
|
||||
/** 打开赞助商的注册 / 接入说明链接(只记录是哪家、哪个入口) */
|
||||
SponsorLinkOpened: 'sponsor_link_opened',
|
||||
} as const
|
||||
|
||||
export type AnalyticsEventName =
|
||||
@@ -55,6 +57,14 @@ export function trackProcessingFailed(props: {
|
||||
trackEvent(AnalyticsEvent.ProcessingFailed, { stage: props.stage, code: props.code })
|
||||
}
|
||||
|
||||
export function trackSponsorLinkOpened(props: {
|
||||
sponsor: 'infistar'
|
||||
target: 'register' | 'guide'
|
||||
placement: 'settings_model'
|
||||
}): void {
|
||||
trackEvent(AnalyticsEvent.SponsorLinkOpened, props)
|
||||
}
|
||||
|
||||
export function trackApiKeyConfigured(props: {
|
||||
provider: string
|
||||
/** 不要传 key 明文,仅标记是否填写 */
|
||||
|
||||
@@ -1122,5 +1122,12 @@
|
||||
"导入任务未能启动,请重试;原素材与已有成片已保留": "Could not start the import. Please retry; your source and existing exports are preserved.",
|
||||
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "If the source cannot play, create a compatible preview. The original stays unchanged; no AI is used.",
|
||||
"正在生成兼容预览,长视频可能需要几分钟…": "Preparing preview; long videos may take a few minutes…",
|
||||
"生成兼容预览": "Create compatible preview"
|
||||
"生成兼容预览": "Create compatible preview",
|
||||
"Infistar 无限星河": "Infistar",
|
||||
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Sponsor. One key for Claude, GPT, Gemini, DeepSeek and more. The endpoint is preset.",
|
||||
"开始使用": "Get started",
|
||||
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Sign up through AutoClip's referral link to claim $5 in trial credit (terms on the promotion page). Then create an API key in the console and paste it below. This is a referral link; commissions support AutoClip's maintenance.",
|
||||
"注册并领取体验额度": "Sign up & claim credit",
|
||||
"接入说明": "Setup guide",
|
||||
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "Once you enter the API key, the models available to your account are listed here. Pick one."
|
||||
}
|
||||
|
||||
@@ -1122,5 +1122,12 @@
|
||||
"导入任务未能启动,请重试;原素材与已有成片已保留": "No se pudo iniciar la importación. Inténtalo de nuevo; el original y las exportaciones existentes se conservan.",
|
||||
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "Si el original no se reproduce, crea una vista previa compatible. No se modifica el original ni se usa IA.",
|
||||
"正在生成兼容预览,长视频可能需要几分钟…": "Preparando vista previa; puede tardar unos minutos…",
|
||||
"生成兼容预览": "Crear vista previa compatible"
|
||||
"生成兼容预览": "Crear vista previa compatible",
|
||||
"Infistar 无限星河": "Infistar",
|
||||
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Patrocinador. Una clave para Claude, GPT, Gemini, DeepSeek y más. El endpoint ya está configurado.",
|
||||
"开始使用": "Empezar",
|
||||
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Regístrate con el enlace de referido de AutoClip para obtener $5 de crédito de prueba (condiciones en la página de la promoción). Después crea una clave API en la consola y pégala abajo. Es un enlace de referido; las comisiones ayudan a mantener AutoClip.",
|
||||
"注册并领取体验额度": "Registrarse y obtener crédito",
|
||||
"接入说明": "Guía de configuración",
|
||||
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "Al introducir la clave API se listan los modelos disponibles para tu cuenta. Elige uno."
|
||||
}
|
||||
|
||||
@@ -1122,5 +1122,12 @@
|
||||
"导入任务未能启动,请重试;原素材与已有成片已保留": "Impossible de démarrer l’importation. Réessayez ; la source et les exports existants sont conservés.",
|
||||
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "Si la source ne se lit pas, créez un aperçu compatible. Original inchangé, sans IA.",
|
||||
"正在生成兼容预览,长视频可能需要几分钟…": "Préparation de l’aperçu ; cela peut prendre quelques minutes…",
|
||||
"生成兼容预览": "Créer un aperçu compatible"
|
||||
"生成兼容预览": "Créer un aperçu compatible",
|
||||
"Infistar 无限星河": "Infistar",
|
||||
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Sponsor. Une seule clé pour Claude, GPT, Gemini, DeepSeek et d’autres. L’endpoint est déjà configuré.",
|
||||
"开始使用": "Commencer",
|
||||
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Inscrivez-vous via le lien de parrainage d’AutoClip pour obtenir 5 $ de crédit d’essai (conditions sur la page de l’offre). Créez ensuite une clé API dans la console et collez-la ci-dessous. Lien de parrainage : les commissions financent la maintenance d’AutoClip.",
|
||||
"注册并领取体验额度": "S’inscrire et obtenir le crédit",
|
||||
"接入说明": "Guide de configuration",
|
||||
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "Une fois la clé API saisie, les modèles disponibles pour votre compte s’affichent ici. Choisissez-en un."
|
||||
}
|
||||
|
||||
@@ -1122,5 +1122,12 @@
|
||||
"导入任务未能启动,请重试;原素材与已有成片已保留": "インポートを開始できませんでした。再試行してください。元の素材と既存の書き出しは保持されています。",
|
||||
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "原動画を再生できない場合は互換プレビューを作成できます。原本は変更せず、AIは使用しません。",
|
||||
"正在生成兼容预览,长视频可能需要几分钟…": "互換プレビューを生成中。長い動画は数分かかる場合があります…",
|
||||
"生成兼容预览": "互換プレビューを作成"
|
||||
"生成兼容预览": "互換プレビューを作成",
|
||||
"Infistar 无限星河": "Infistar(無限星河)",
|
||||
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "スポンサー。1 つのキーで Claude、GPT、Gemini、DeepSeek などを利用できます。接続先は設定済みです。",
|
||||
"开始使用": "はじめる",
|
||||
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "AutoClip 専用の紹介リンクから登録すると $5 分の体験クレジットを受け取れます(条件はキャンペーンページを参照)。登録後、コンソールで API キーを作成して下に貼り付けてください。紹介報酬はプロジェクトの維持に使われます。",
|
||||
"注册并领取体验额度": "登録してクレジットを受け取る",
|
||||
"接入说明": "設定ガイド",
|
||||
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "API キーを入力すると、このアカウントで使えるモデルが一覧表示されます。1 つ選んでください。"
|
||||
}
|
||||
|
||||
@@ -1122,5 +1122,12 @@
|
||||
"导入任务未能启动,请重试;原素材与已有成片已保留": "가져오기를 시작하지 못했습니다. 다시 시도해 주세요. 원본과 기존 내보내기는 보존됩니다.",
|
||||
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "원본을 재생할 수 없다면 호환 미리보기를 만드세요. 원본은 변경되지 않으며 AI를 사용하지 않습니다.",
|
||||
"正在生成兼容预览,长视频可能需要几分钟…": "미리보기 생성 중. 긴 동영상은 몇 분 걸릴 수 있습니다…",
|
||||
"生成兼容预览": "호환 미리보기 생성"
|
||||
"生成兼容预览": "호환 미리보기 생성",
|
||||
"Infistar 无限星河": "Infistar(무한성하)",
|
||||
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "후원 파트너. 키 하나로 Claude, GPT, Gemini, DeepSeek 등을 사용할 수 있습니다. 엔드포인트는 미리 설정되어 있습니다.",
|
||||
"开始使用": "시작하기",
|
||||
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "AutoClip 전용 추천 링크로 가입하면 $5 체험 크레딧을 받을 수 있습니다(조건은 이벤트 페이지 기준). 가입 후 콘솔에서 API 키를 만들어 아래에 붙여 넣으세요. 추천 수수료는 프로젝트 유지에 쓰입니다.",
|
||||
"注册并领取体验额度": "가입하고 크레딧 받기",
|
||||
"接入说明": "설정 안내",
|
||||
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "API 키를 입력하면 이 계정에서 쓸 수 있는 모델이 표시됩니다. 하나를 고르세요."
|
||||
}
|
||||
|
||||
@@ -1122,5 +1122,12 @@
|
||||
"导入任务未能启动,请重试;原素材与已有成片已保留": "Não foi possível iniciar a importação. Tente novamente; o original e as exportações existentes foram preservados.",
|
||||
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "Se o original não reproduzir, crie uma prévia compatível. O original não muda e nenhuma IA é usada.",
|
||||
"正在生成兼容预览,长视频可能需要几分钟…": "Preparando prévia; vídeos longos podem levar alguns minutos…",
|
||||
"生成兼容预览": "Criar prévia compatível"
|
||||
"生成兼容预览": "Criar prévia compatível",
|
||||
"Infistar 无限星河": "Infistar",
|
||||
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Patrocinador. Uma chave para Claude, GPT, Gemini, DeepSeek e outros. O endpoint já está configurado.",
|
||||
"开始使用": "Começar",
|
||||
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Cadastre-se pelo link de indicação do AutoClip para receber US$ 5 de crédito de teste (condições na página da promoção). Depois crie uma chave de API no console e cole abaixo. É um link de indicação; as comissões ajudam a manter o AutoClip.",
|
||||
"注册并领取体验额度": "Cadastrar e receber crédito",
|
||||
"接入说明": "Guia de configuração",
|
||||
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "Ao inserir a chave de API, os modelos disponíveis para sua conta aparecem aqui. Escolha um."
|
||||
}
|
||||
|
||||
@@ -1122,5 +1122,12 @@
|
||||
"导入任务未能启动,请重试;原素材与已有成片已保留": "Не удалось запустить импорт. Повторите попытку; исходный материал и готовые файлы сохранены.",
|
||||
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "Если исходное видео не воспроизводится, создайте совместимый предпросмотр. Оригинал не меняется, ИИ не используется.",
|
||||
"正在生成兼容预览,长视频可能需要几分钟…": "Подготовка предпросмотра может занять несколько минут…",
|
||||
"生成兼容预览": "Создать совместимый предпросмотр"
|
||||
"生成兼容预览": "Создать совместимый предпросмотр",
|
||||
"Infistar 无限星河": "Infistar",
|
||||
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Спонсор. Один ключ для Claude, GPT, Gemini, DeepSeek и других моделей. Адрес API уже указан.",
|
||||
"开始使用": "Начало работы",
|
||||
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Зарегистрируйтесь по реферальной ссылке AutoClip и получите $5 пробного баланса (условия — на странице акции). Затем создайте API-ключ в консоли и вставьте его ниже. Это реферальная ссылка; комиссия идёт на поддержку AutoClip.",
|
||||
"注册并领取体验额度": "Зарегистрироваться и получить баланс",
|
||||
"接入说明": "Инструкция",
|
||||
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "После ввода API-ключа здесь появятся модели, доступные вашему аккаунту. Выберите одну."
|
||||
}
|
||||
|
||||
@@ -1122,5 +1122,12 @@
|
||||
"导入任务未能启动,请重试;原素材与已有成片已保留": "导入任务未能启动,请重试;原素材与已有成片已保留",
|
||||
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "原片无法播放时,可生成兼容预览;原片不变,不调用模型。",
|
||||
"正在生成兼容预览,长视频可能需要几分钟…": "正在生成兼容预览,长视频可能需要几分钟…",
|
||||
"生成兼容预览": "生成兼容预览"
|
||||
"生成兼容预览": "生成兼容预览",
|
||||
"Infistar 无限星河": "Infistar 无限星河",
|
||||
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。",
|
||||
"开始使用": "开始使用",
|
||||
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。",
|
||||
"注册并领取体验额度": "注册并领取体验额度",
|
||||
"接入说明": "接入说明",
|
||||
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "填写 API Key 后会自动列出该账号可用的模型,选一个即可。"
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import PublishSettings from '../components/PublishSettings'
|
||||
import CoverSettings from '../components/CoverSettings'
|
||||
import { isDesktopMode } from '../utils/desktopMode'
|
||||
import { openExternalLink } from '../utils/externalLinks'
|
||||
import { trackApiKeyConfigured } from '../analytics/events'
|
||||
import { trackApiKeyConfigured, trackSponsorLinkOpened } from '../analytics/events'
|
||||
import { isAnalyticsEnabled, setAnalyticsEnabled } from '../analytics/posthog'
|
||||
import { getRuntimeInfo } from '../analytics/lifecycle'
|
||||
import { isCrashReportsEnabled, setCrashReportsEnabled } from '../desktop/sentry'
|
||||
@@ -35,12 +35,15 @@ const toNumber = (v: unknown, fallback: number): number => {
|
||||
return Number.isFinite(n) ? n : fallback
|
||||
}
|
||||
|
||||
type ProviderKey = 'dashscope' | 'openai' | 'gemini' | 'deepseek' | 'seed' | 'kimi' | 'glm' | 'grok' | 'ollama' | 'lmstudio'
|
||||
type ProviderKey = 'dashscope' | 'openai' | 'infistar' | 'gemini' | 'deepseek' | 'seed' | 'kimi' | 'glm' | 'grok' | 'ollama' | 'lmstudio'
|
||||
type LocalPreset = { baseUrl: string; defaultModel: string; docsUrl: string; app: string }
|
||||
type CloudPreset = { baseUrl: string; defaultModel: string }
|
||||
const PROVIDERS: Record<ProviderKey, { name: string; short: string; hint: string; apiKeyField: string; placeholder: string; keyUrl: string; local?: LocalPreset; cloud?: CloudPreset }> = {
|
||||
type Sponsor = { registerUrl: string; guideUrl: string }
|
||||
const PROVIDERS: Record<ProviderKey, { name: string; short: string; hint: string; apiKeyField: string; placeholder: string; keyUrl: string; local?: LocalPreset; cloud?: CloudPreset; sponsor?: Sponsor }> = {
|
||||
dashscope: { get name() { return t("阿里通义千问") }, get short() { return t("通义千问") }, get hint() { return t("阿里云 DashScope。国内直连,qwen-plus 性价比高。") }, apiKeyField: 'dashscope_api_key', placeholder: 'sk-…', keyUrl: 'https://dashscope.console.aliyun.com/apiKey' },
|
||||
openai: { get name() { return t("OpenAI / 兼容接口") }, get short() { return t("OpenAI 兼容") }, get hint() { return t("OpenAI,或任何兼容接口:OpenRouter、vLLM。") }, apiKeyField: 'openai_api_key', get placeholder() { return t("sk-…(自建服务可留空)") }, keyUrl: 'https://platform.openai.com/api-keys' },
|
||||
// 赞助合作伙伴(docs/INFISTAR_SETUP.md)。多模型网关,型号随账号而定:不预设默认模型,填好 key 后实时拉取
|
||||
infistar: { get name() { return t("Infistar 无限星河") }, short: 'Infistar', get hint() { return t("赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。") }, apiKeyField: 'infistar_api_key', placeholder: 'sk-…', keyUrl: 'https://www.infistar.cc/register?aff=XLK3BCM6&ref_source=link', cloud: { baseUrl: 'https://infistar.cc/v1', defaultModel: '' }, sponsor: { registerUrl: 'https://www.infistar.cc/register?aff=XLK3BCM6&ref_source=link', guideUrl: 'https://github.com/zhouxiaoka/autoclip/blob/main/docs/INFISTAR_SETUP.md' } },
|
||||
gemini: { name: 'Google Gemini', short: 'Gemini', get hint() { return t("Google AI Studio 的 Gemini 系列。") }, apiKeyField: 'gemini_api_key', placeholder: 'AIza…', keyUrl: 'https://aistudio.google.com/apikey' },
|
||||
deepseek: { name: 'DeepSeek', short: 'DeepSeek', get hint() { return t("DeepSeek 官方。国内直连,deepseek-flash 是当前 V4.1。") }, apiKeyField: 'deepseek_api_key', placeholder: 'sk-…', keyUrl: 'https://platform.deepseek.com/api_keys', cloud: { baseUrl: 'https://api.deepseek.com', defaultModel: 'deepseek-flash' } },
|
||||
seed: { name: 'Seed', short: 'Seed', get hint() { return t("火山方舟 Seed。国内直连,豆包 Seed 2.1 系列。") }, apiKeyField: 'seed_api_key', placeholder: '…', keyUrl: 'https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey', cloud: { baseUrl: 'https://ark.cn-beijing.volces.com/api/v3', defaultModel: 'doubao-seed-2-1-lite-260915' } },
|
||||
@@ -68,11 +71,12 @@ const FALLBACK_CATALOG: Record<string, string[]> = {
|
||||
kimi: ['kimi-k3', 'kimi-k2.6', 'kimi-k2.5', 'kimi-k2.7-code'],
|
||||
glm: ['glm-5.3', 'glm-5.2', 'glm-4.7'],
|
||||
grok: ['grok-4.6', 'grok-4.5', 'grok-4.3'],
|
||||
infistar: [],
|
||||
}
|
||||
const PROVIDER_GROUP_ORDER: ProviderKey[] = ['dashscope', 'openai', 'gemini', 'deepseek', 'seed', 'kimi', 'glm', 'grok']
|
||||
const PROVIDER_GROUP_ORDER: ProviderKey[] = ['dashscope', 'openai', 'infistar', 'gemini', 'deepseek', 'seed', 'kimi', 'glm', 'grok']
|
||||
const providerGroupLabel = (key: string) => ({
|
||||
dashscope: t("通义千问"), openai: 'OpenAI', gemini: 'Gemini', deepseek: 'DeepSeek',
|
||||
seed: 'Seed', kimi: 'Kimi', glm: 'GLM', grok: 'Grok',
|
||||
seed: 'Seed', kimi: 'Kimi', glm: 'GLM', grok: 'Grok', infistar: 'Infistar',
|
||||
} as Record<string, string>)[key] || key
|
||||
const knownCloudModels = (catalog: Record<string, string[]>, extra: string[] = []) =>
|
||||
new Set([...Object.values(catalog).flat(), ...extra])
|
||||
@@ -93,7 +97,7 @@ const cloudModelOptions = (
|
||||
|
||||
const CLOUD_DEFAULT_MODEL: Partial<Record<ProviderKey, string>> = {
|
||||
dashscope: 'qwen-plus', openai: 'gpt-5-mini', gemini: 'gemini-3.8-flash', deepseek: 'deepseek-flash',
|
||||
seed: 'doubao-seed-2-1-lite-260915', kimi: 'kimi-k2.6', glm: 'glm-5.3', grok: 'grok-4.6',
|
||||
seed: 'doubao-seed-2-1-lite-260915', kimi: 'kimi-k2.6', glm: 'glm-5.3', grok: 'grok-4.6', infistar: undefined,
|
||||
}
|
||||
|
||||
type SectionKey = 'analysis' | 'vision' | 'model' | 'speech' | 'app' | 'publish' | 'cover' | 'feedback'
|
||||
@@ -174,6 +178,7 @@ const SettingsPage: React.FC = () => {
|
||||
kimi_api_key: settingsData.api?.api_keys?.kimi || '',
|
||||
glm_api_key: settingsData.api?.api_keys?.glm || '',
|
||||
grok_api_key: settingsData.api?.api_keys?.grok || '',
|
||||
infistar_api_key: settingsData.api?.api_keys?.infistar || '',
|
||||
seed_api_key: settingsData.api?.api_keys?.seed || '',
|
||||
jimeng_access_key: settingsData.api?.api_keys?.jimeng_access || '',
|
||||
jimeng_secret_key: settingsData.api?.api_keys?.jimeng_secret || '',
|
||||
@@ -212,6 +217,7 @@ const SettingsPage: React.FC = () => {
|
||||
kimi: values.kimi_api_key || keys.kimi || '',
|
||||
glm: values.glm_api_key || keys.glm || '',
|
||||
grok: values.grok_api_key || keys.grok || '',
|
||||
infistar: values.infistar_api_key || keys.infistar || '',
|
||||
seed: values.seed_api_key || keys.seed || '',
|
||||
jimeng_access: values.jimeng_access_key || keys.jimeng_access || '',
|
||||
jimeng_secret: values.jimeng_secret_key || keys.jimeng_secret || ''
|
||||
@@ -476,6 +482,19 @@ const SettingsPage: React.FC = () => {
|
||||
</Row>
|
||||
)}
|
||||
|
||||
{cfg.sponsor && (
|
||||
<Row
|
||||
wide
|
||||
label={t("开始使用")}
|
||||
hint={t("通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。")}
|
||||
>
|
||||
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
||||
<Btn variant="cta" size="sm" onClick={() => { trackSponsorLinkOpened({ sponsor: 'infistar', target: 'register', placement: 'settings_model' }); openExternalLink(cfg.sponsor!.registerUrl) }}>{t("注册并领取体验额度")}</Btn>
|
||||
<Btn size="sm" onClick={() => { trackSponsorLinkOpened({ sponsor: 'infistar', target: 'guide', placement: 'settings_model' }); openExternalLink(cfg.sponsor!.guideUrl) }}>{t("接入说明")}</Btn>
|
||||
</div>
|
||||
</Row>
|
||||
)}
|
||||
|
||||
{!localCfg && <Row
|
||||
wide
|
||||
label="API Key"
|
||||
@@ -512,6 +531,8 @@ const SettingsPage: React.FC = () => {
|
||||
? <>{t("已拉取最新模型数量", { count: cloudModels.models.length })} <a onClick={() => void loadCloudModels(selectedProvider, { refresh: true })} style={{ color: 'var(--ac-accent)', cursor: 'pointer' }}>{t("刷新")}</a></>
|
||||
: usingCustomEndpoint
|
||||
? <>{t("填该服务实际提供的模型名(如 glm-4-flash、deepseek-chat、qwen2.5:7b),回车确认。")} <a onClick={() => void loadCloudModels(selectedProvider, { refresh: true })} style={{ color: 'var(--ac-accent)', cursor: 'pointer' }}>{t("刷新")}</a></>
|
||||
: cfg.sponsor && !cloudModels.models.length
|
||||
? <>{t("填写 API Key 后会自动列出该账号可用的模型,选一个即可。")} <a onClick={() => void loadCloudModels(selectedProvider, { refresh: true })} style={{ color: 'var(--ac-accent)', cursor: 'pointer' }}>{t("刷新")}</a></>
|
||||
: <>{t("可直接输入模型名,回车确认。")} {t("填写密钥后可拉取该账号可用的最新模型。")} <a onClick={() => void loadCloudModels(selectedProvider, { refresh: true })} style={{ color: 'var(--ac-accent)', cursor: 'pointer' }}>{t("刷新")}</a></>}
|
||||
>
|
||||
<Form.Item name="model_name" style={{ width: '100%' }} rules={[{ required: true, message: t("请输入或选择模型") }]}>
|
||||
|
||||
Reference in New Issue
Block a user