diff --git a/internal/pack/source_loader_test.go b/internal/pack/source_loader_test.go index 3646c7d9..9a5dba90 100644 --- a/internal/pack/source_loader_test.go +++ b/internal/pack/source_loader_test.go @@ -19,6 +19,36 @@ func TestLoadPathSupportsDirectory(t *testing.T) { } } +func TestLoadPathIncludesFirstBatchOfficialProviders(t *testing.T) { + loaded, err := LoadPath(filepath.Join("..", "..", "packs", "openai-cn-pack")) + if err != nil { + t.Fatalf("LoadPath(dir) error = %v", err) + } + + got := make(map[string]struct{}, len(loaded.Providers)) + for _, provider := range loaded.Providers { + got[provider.ProviderID] = struct{}{} + } + + want := []string{ + "qwen-official", + "qwen-coder-official", + "deepseek-chat-official", + "deepseek-reasoner-official", + "glm-5-1-official", + "glm-4-7-official", + "kimi-k2-5-official", + "kimi-k2-thinking-official", + "minimax-m2-7-official", + "step-3-5-flash-official", + } + for _, providerID := range want { + if _, ok := got[providerID]; !ok { + t.Fatalf("Providers missing %q; got %v", providerID, providerIDs(loaded.Providers)) + } + } +} + func TestLoadPathSupportsZipArchive(t *testing.T) { tempDir := t.TempDir() archivePath := filepath.Join(tempDir, "openai-cn-pack.zip") @@ -86,3 +116,11 @@ func writePackArchive(t *testing.T, archivePath string) { t.Fatalf("Close archive writer: %v", err) } } + +func providerIDs(providers []ProviderManifest) []string { + ids := make([]string, 0, len(providers)) + for _, provider := range providers { + ids = append(ids, provider.ProviderID) + } + return ids +} diff --git a/packs/openai-cn-pack/README.md b/packs/openai-cn-pack/README.md index 61a770db..65db2396 100644 --- a/packs/openai-cn-pack/README.md +++ b/packs/openai-cn-pack/README.md @@ -9,10 +9,60 @@ - 真实可校验包:`pack.json`、`providers/deepseek.json`、`checksums.txt` - 协议样例:`pack.json.example`、`providers/deepseek.json.example` -后续真实交付时,可以扩展更多 provider: +当前 pack 除了历史中转 provider,也已经内置首批官方 provider 模板: + +- `qwen-official.json` +- `qwen-coder-official.json` +- `deepseek-chat-official.json` +- `deepseek-reasoner-official.json` +- `glm-5-1-official.json` +- `glm-4-7-official.json` +- `kimi-k2-5-official.json` +- `kimi-k2-thinking-official.json` +- `minimax-m2-7-official.json` +- `step-3-5-flash-official.json` + +对应的 `provider_id` 与首选模型如下: + +- `qwen-official` + - `qwen-plus`, `qwen-max` +- `qwen-coder-official` + - `qwen3-coder-plus`, `qwen3-coder-flash` +- `deepseek-chat-official` + - `deepseek-chat` +- `deepseek-reasoner-official` + - `deepseek-reasoner` +- `glm-5-1-official` + - `glm-5.1` +- `glm-4-7-official` + - `glm-4.7` +- `kimi-k2-5-official` + - `kimi-k2.5` +- `kimi-k2-thinking-official` + - `kimi-k2-thinking` +- `minimax-m2-7-official` + - `MiniMax-M2.7-highspeed`, `MiniMax-M2.5-highspeed` +- `step-3-5-flash-official` + - `step-3.5-flash` + +一旦这些 provider 模板已经内置到 pack,后续新增同类官方 key 的导入就不需要再改代码或重写 provider JSON,直接走标准导入命令即可。例如导入 Qwen: + +```bash +go run ./cmd/cli import-provider \ + --host-base-url https://sub2api.example.com \ + --host-api-key \ + --pack-dir ./packs/openai-cn-pack \ + --provider-id qwen-official \ + --keys , \ + --access-mode self_service \ + --access-api-key +``` + +如果你要导入的不是这 10 个模板之一,而是一个全新的官方 provider,那么仍然需要先补一个新的 provider manifest,再做一键导入。 + +后续真实交付时,还可以继续扩展更多 provider: - `kimi.json` - `qwen.json` - `glm.json` - `minimax.json` - diff --git a/packs/openai-cn-pack/checksums.txt b/packs/openai-cn-pack/checksums.txt index a1a156dd..cdf3b56e 100644 --- a/packs/openai-cn-pack/checksums.txt +++ b/packs/openai-cn-pack/checksums.txt @@ -1,4 +1,14 @@ -3e3326e40d51a3753adc6fde0aa8859dc5d2076726a692aae45e36f7b27c89d6 pack.json +303bfaea55379f4a4329bd7f720b9c692981dd486a31176b6b93731f56b18cbc providers/minimax-m2-7-official.json +391c3aa02b669eb591f2a3dda45500d66e6a519f07a05c158c8de6be69313e54 providers/glm-4-7-official.json +437028a75810bd970915ec31db1b415d384052143e404fcaa66e335ef2865ae3 providers/qwen-coder-official.json +4817f3faa54dd7fb20cf25a2ded0e702286d55ad829e686c125b70fc55cd52d6 providers/qwen-official.json +51c8ab51666002c40f0f91744fbb5039d4a97c8c4bbb0b67c5936a5b5f8bf0bc providers/kimi-k2-5-official.json 5d33003fb6fefaf2dbb8445be7c18cc817d266215bc996ae91b30fbed5a98e7b providers/deepseek.json 5dcc402daddacce6dcaceb1501020342f1b1121fbffe9097ede4d5aae072f84e providers/minimax.json +65e3a1a5e56889ddb0474a3b55294aceb6920fa72dcf6f2c56d3199462daa4cf providers/kimi-k2-thinking-official.json +a39de44fa68fcb5ee9c3ef38ed3bd5c30acd23cacd2f618d670de0bf9e7096e3 providers/deepseek-reasoner-official.json +e3da0745a14cb76f7275bfef90b40a6f652f4dce2efd95e44c27fe2e81f4eea5 pack.json +eda16afc83e12055d3a41b5e37fd0923d3741b66da5af780bcea53ff34fa130e providers/step-3-5-flash-official.json fa486a449407f38de8b180ff301568deccef5177ca0436158b1d5b0e6d9328b2 providers/openai-zhongzhuan.json +fdf7fa2e1ff4aa4f5dcd3f3ec2f55db11d6197625a467d6d0afa8a554a6ba6e6 providers/deepseek-chat-official.json +fe8c84b1b316e8c2e9eb60411383d04bfc0f0ff0c029db3b7d83aa976a6f6d54 providers/glm-5-1-official.json diff --git a/packs/openai-cn-pack/pack.json b/packs/openai-cn-pack/pack.json index c3673c4b..78154ded 100644 --- a/packs/openai-cn-pack/pack.json +++ b/packs/openai-cn-pack/pack.json @@ -1,6 +1,6 @@ { "pack_id": "openai-cn-pack", - "version": "1.0.1", + "version": "1.1.0", "vendor": "YourTeam", "target_host": "sub2api", "min_host_version": "0.1.126", diff --git a/packs/openai-cn-pack/providers/deepseek-chat-official.json b/packs/openai-cn-pack/providers/deepseek-chat-official.json new file mode 100644 index 00000000..876e8ac3 --- /dev/null +++ b/packs/openai-cn-pack/providers/deepseek-chat-official.json @@ -0,0 +1,30 @@ +{ + "provider_id": "deepseek-chat-official", + "display_name": "DeepSeek Chat 官方兼容", + "base_url": "https://api.deepseek.com/v1", + "platform": "openai", + "account_type": "apikey", + "default_models": ["deepseek-chat"], + "smoke_test_model": "deepseek-chat", + "group_template": { + "name": "DeepSeek Chat 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "DeepSeek Chat 官方默认渠道", + "model_mapping": { + "deepseek-chat": "deepseek-chat" + } + }, + "plan_template": { + "name": "DeepSeek Chat 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/deepseek-reasoner-official.json b/packs/openai-cn-pack/providers/deepseek-reasoner-official.json new file mode 100644 index 00000000..bcddf4e9 --- /dev/null +++ b/packs/openai-cn-pack/providers/deepseek-reasoner-official.json @@ -0,0 +1,30 @@ +{ + "provider_id": "deepseek-reasoner-official", + "display_name": "DeepSeek Reasoner 官方兼容", + "base_url": "https://api.deepseek.com/v1", + "platform": "openai", + "account_type": "apikey", + "default_models": ["deepseek-reasoner"], + "smoke_test_model": "deepseek-reasoner", + "group_template": { + "name": "DeepSeek Reasoner 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "DeepSeek Reasoner 官方默认渠道", + "model_mapping": { + "deepseek-reasoner": "deepseek-reasoner" + } + }, + "plan_template": { + "name": "DeepSeek Reasoner 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/glm-4-7-official.json b/packs/openai-cn-pack/providers/glm-4-7-official.json new file mode 100644 index 00000000..7329cc46 --- /dev/null +++ b/packs/openai-cn-pack/providers/glm-4-7-official.json @@ -0,0 +1,30 @@ +{ + "provider_id": "glm-4-7-official", + "display_name": "GLM 4.7 官方兼容", + "base_url": "https://open.bigmodel.cn/api/paas/v4", + "platform": "openai", + "account_type": "apikey", + "default_models": ["glm-4.7"], + "smoke_test_model": "glm-4.7", + "group_template": { + "name": "GLM 4.7 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "GLM 4.7 官方默认渠道", + "model_mapping": { + "glm-4.7": "glm-4.7" + } + }, + "plan_template": { + "name": "GLM 4.7 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/glm-5-1-official.json b/packs/openai-cn-pack/providers/glm-5-1-official.json new file mode 100644 index 00000000..53e490e6 --- /dev/null +++ b/packs/openai-cn-pack/providers/glm-5-1-official.json @@ -0,0 +1,30 @@ +{ + "provider_id": "glm-5-1-official", + "display_name": "GLM 5.1 官方兼容", + "base_url": "https://open.bigmodel.cn/api/paas/v4", + "platform": "openai", + "account_type": "apikey", + "default_models": ["glm-5.1"], + "smoke_test_model": "glm-5.1", + "group_template": { + "name": "GLM 5.1 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "GLM 5.1 官方默认渠道", + "model_mapping": { + "glm-5.1": "glm-5.1" + } + }, + "plan_template": { + "name": "GLM 5.1 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/kimi-k2-5-official.json b/packs/openai-cn-pack/providers/kimi-k2-5-official.json new file mode 100644 index 00000000..e0b1102c --- /dev/null +++ b/packs/openai-cn-pack/providers/kimi-k2-5-official.json @@ -0,0 +1,30 @@ +{ + "provider_id": "kimi-k2-5-official", + "display_name": "Kimi K2.5 官方兼容", + "base_url": "https://api.moonshot.cn/v1", + "platform": "openai", + "account_type": "apikey", + "default_models": ["kimi-k2.5"], + "smoke_test_model": "kimi-k2.5", + "group_template": { + "name": "Kimi K2.5 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "Kimi K2.5 官方默认渠道", + "model_mapping": { + "kimi-k2.5": "kimi-k2.5" + } + }, + "plan_template": { + "name": "Kimi K2.5 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/kimi-k2-thinking-official.json b/packs/openai-cn-pack/providers/kimi-k2-thinking-official.json new file mode 100644 index 00000000..747b180a --- /dev/null +++ b/packs/openai-cn-pack/providers/kimi-k2-thinking-official.json @@ -0,0 +1,30 @@ +{ + "provider_id": "kimi-k2-thinking-official", + "display_name": "Kimi K2 Thinking 官方兼容", + "base_url": "https://api.moonshot.cn/v1", + "platform": "openai", + "account_type": "apikey", + "default_models": ["kimi-k2-thinking"], + "smoke_test_model": "kimi-k2-thinking", + "group_template": { + "name": "Kimi K2 Thinking 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "Kimi K2 Thinking 官方默认渠道", + "model_mapping": { + "kimi-k2-thinking": "kimi-k2-thinking" + } + }, + "plan_template": { + "name": "Kimi K2 Thinking 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/minimax-m2-7-official.json b/packs/openai-cn-pack/providers/minimax-m2-7-official.json new file mode 100644 index 00000000..4b635496 --- /dev/null +++ b/packs/openai-cn-pack/providers/minimax-m2-7-official.json @@ -0,0 +1,31 @@ +{ + "provider_id": "minimax-m2-7-official", + "display_name": "MiniMax M2.7 官方兼容", + "base_url": "https://api.minimaxi.com/v1", + "platform": "openai", + "account_type": "apikey", + "default_models": ["MiniMax-M2.7-highspeed", "MiniMax-M2.5-highspeed"], + "smoke_test_model": "MiniMax-M2.7-highspeed", + "group_template": { + "name": "MiniMax M2.7 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "MiniMax M2.7 官方默认渠道", + "model_mapping": { + "MiniMax-M2.7-highspeed": "MiniMax-M2.7-highspeed", + "MiniMax-M2.5-highspeed": "MiniMax-M2.5-highspeed" + } + }, + "plan_template": { + "name": "MiniMax M2.7 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/qwen-coder-official.json b/packs/openai-cn-pack/providers/qwen-coder-official.json new file mode 100644 index 00000000..e4b5e68f --- /dev/null +++ b/packs/openai-cn-pack/providers/qwen-coder-official.json @@ -0,0 +1,31 @@ +{ + "provider_id": "qwen-coder-official", + "display_name": "Qwen Coder 官方兼容", + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "platform": "openai", + "account_type": "apikey", + "default_models": ["qwen3-coder-plus", "qwen3-coder-flash"], + "smoke_test_model": "qwen3-coder-plus", + "group_template": { + "name": "Qwen Coder 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "Qwen Coder 官方默认渠道", + "model_mapping": { + "qwen3-coder-plus": "qwen3-coder-plus", + "qwen3-coder-flash": "qwen3-coder-flash" + } + }, + "plan_template": { + "name": "Qwen Coder 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/qwen-official.json b/packs/openai-cn-pack/providers/qwen-official.json new file mode 100644 index 00000000..ede6a8c2 --- /dev/null +++ b/packs/openai-cn-pack/providers/qwen-official.json @@ -0,0 +1,31 @@ +{ + "provider_id": "qwen-official", + "display_name": "Qwen 官方兼容", + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "platform": "openai", + "account_type": "apikey", + "default_models": ["qwen-plus", "qwen-max"], + "smoke_test_model": "qwen-plus", + "group_template": { + "name": "Qwen 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "Qwen 官方默认渠道", + "model_mapping": { + "qwen-plus": "qwen-plus", + "qwen-max": "qwen-max" + } + }, + "plan_template": { + "name": "Qwen 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +} diff --git a/packs/openai-cn-pack/providers/step-3-5-flash-official.json b/packs/openai-cn-pack/providers/step-3-5-flash-official.json new file mode 100644 index 00000000..d842b0af --- /dev/null +++ b/packs/openai-cn-pack/providers/step-3-5-flash-official.json @@ -0,0 +1,30 @@ +{ + "provider_id": "step-3-5-flash-official", + "display_name": "Step 3.5 Flash 官方兼容", + "base_url": "https://api.stepfun.com/v1", + "platform": "openai", + "account_type": "apikey", + "default_models": ["step-3.5-flash"], + "smoke_test_model": "step-3.5-flash", + "group_template": { + "name": "Step 3.5 Flash 官方默认分组", + "rate_multiplier": 1.0 + }, + "channel_template": { + "name": "Step 3.5 Flash 官方默认渠道", + "model_mapping": { + "step-3.5-flash": "step-3.5-flash" + } + }, + "plan_template": { + "name": "Step 3.5 Flash 官方默认套餐", + "price": 19.9, + "validity_days": 30, + "validity_unit": "day" + }, + "import": { + "supports_multi_key": true, + "supports_strict": true, + "supports_partial": true + } +}