mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-10-25 17:22:27 +08:00
feat(usage): enable coding-plan usage by default for every app
Adding a provider whose base URL matches a coding plan (Kimi, Zhipu, MiniMax, Volcengine, OpenCode Go, Command Code) now turns on the token_plan usage query in every app, not only Claude Code. Before, other apps got it only for OpenCode Go and Codex + Command Code, so a Kimi plan added to Codex, OpenCode, Pi, Hermes etc. had usage off until enabled by hand. The quota endpoints only depend on the API key (Zhipu also on the host), not on the client protocol or base URL path, and the backend already resolves usage credentials for all apps. The frontend base URL lookup now also covers Gemini CLI, Grok Build, Hermes, OpenClaw and MiniMax Code. ZenMux stays Claude-only: its query GETs the configured base URL itself, which is untested for other apps' inference URLs. Existing providers are not changed.
This commit is contained in:
1 parent
3c918cd0a7
commit
c859026d48
3 files changed
+68
-27
No files matched your search
@@ -86,11 +86,32 @@ describe("extractBaseUrlForUsageDetection", () => {
|
||||
).toBe("https://opencode.ai/zen/go/v1");
|
||||
});
|
||||
|
||||
it("returns null for unsupported apps", () => {
|
||||
it("reads the remaining apps' native base URL fields", () => {
|
||||
const kimi = "https://api.kimi.com/coding/v1";
|
||||
expect(
|
||||
extractBaseUrlForUsageDetection("gemini", {
|
||||
env: { GOOGLE_GEMINI_BASE_URL: "https://opencode.ai/zen/go" },
|
||||
env: { GOOGLE_GEMINI_BASE_URL: kimi },
|
||||
}),
|
||||
).toBe(kimi);
|
||||
expect(
|
||||
extractBaseUrlForUsageDetection("grokbuild", {
|
||||
config: `[models]\ndefault = "k"\n\n[model.k]\nmodel = "kimi-for-coding"\nbase_url = "${kimi}"\n`,
|
||||
}),
|
||||
).toBe(kimi);
|
||||
expect(extractBaseUrlForUsageDetection("hermes", { base_url: kimi })).toBe(
|
||||
kimi,
|
||||
);
|
||||
expect(extractBaseUrlForUsageDetection("openclaw", { baseUrl: kimi })).toBe(
|
||||
kimi,
|
||||
);
|
||||
expect(
|
||||
extractBaseUrlForUsageDetection("mcode", { options: { baseURL: kimi } }),
|
||||
).toBe(kimi);
|
||||
});
|
||||
|
||||
it("returns null for unknown apps", () => {
|
||||
expect(
|
||||
extractBaseUrlForUsageDetection("unknown", { baseUrl: "https://x" }),
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -154,14 +175,26 @@ describe("injectCodingPlanUsageScript", () => {
|
||||
expect(injected.meta?.usage_script?.codingPlanProvider).toBe("kimi");
|
||||
});
|
||||
|
||||
it("does not extend other coding plans to non-claude apps", () => {
|
||||
// 智谱/Kimi 等在其他 app 的自动注入未逐一验证,仅 OpenCode Go 放行
|
||||
const provider: TestProvider = {
|
||||
settingsConfig: {
|
||||
options: { baseURL: "https://open.bigmodel.cn/api/anthropic" },
|
||||
},
|
||||
};
|
||||
expect(inject("opencode", provider).meta?.usage_script).toBeUndefined();
|
||||
it("injects every coding plan for non-claude apps", () => {
|
||||
expect(
|
||||
inject("opencode", {
|
||||
settingsConfig: {
|
||||
options: { baseURL: "https://open.bigmodel.cn/api/anthropic" },
|
||||
},
|
||||
}).meta?.usage_script,
|
||||
).toMatchObject({ enabled: true, codingPlanProvider: "zhipu" });
|
||||
expect(
|
||||
inject("hermes", {
|
||||
settingsConfig: { base_url: "https://api.kimi.com/coding/v1" },
|
||||
}).meta?.usage_script,
|
||||
).toMatchObject({ enabled: true, codingPlanProvider: "kimi" });
|
||||
});
|
||||
|
||||
it("keeps ZenMux claude-only", () => {
|
||||
const settingsConfig = { options: { baseURL: "https://zenmux.ai/api/v1" } };
|
||||
expect(
|
||||
inject("opencode", { settingsConfig }).meta?.usage_script,
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("never overwrites an existing usage_script", () => {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import { createUsageScript } from "@/types";
|
||||
import { TEMPLATE_TYPES } from "@/config/constants";
|
||||
import { extractCodexBaseUrl } from "@/utils/providerConfigUtils";
|
||||
import { extractGrokBuildBaseUrl } from "@/utils/grokBuildConfig";
|
||||
|
||||
export interface CodingPlanProviderEntry {
|
||||
/** 与后端 QuotaTier 的 `codingPlanProvider` 取值对齐 */
|
||||
@@ -121,12 +122,26 @@ export function extractBaseUrlForUsageDetection(
|
||||
: null,
|
||||
);
|
||||
break;
|
||||
case "gemini":
|
||||
raw = settingsConfig.env?.GOOGLE_GEMINI_BASE_URL;
|
||||
break;
|
||||
case "grokbuild":
|
||||
raw =
|
||||
typeof settingsConfig.config === "string"
|
||||
? extractGrokBuildBaseUrl(settingsConfig.config)
|
||||
: null;
|
||||
break;
|
||||
case "opencode":
|
||||
case "mcode":
|
||||
raw = settingsConfig.options?.baseURL;
|
||||
break;
|
||||
case "pi":
|
||||
case "openclaw":
|
||||
raw = settingsConfig.baseUrl;
|
||||
break;
|
||||
case "hermes":
|
||||
raw = settingsConfig.base_url;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -138,11 +153,10 @@ export function extractBaseUrlForUsageDetection(
|
||||
* `meta.usage_script` 标记为 token_plan 并启用。
|
||||
*
|
||||
* - 仅在 `meta.usage_script` 完全缺失时注入,不覆盖用户/UsageScriptModal 已有配置
|
||||
* - Claude app 保持既有行为:命中任意 Coding Plan 供应商都注入;
|
||||
* 其余 app 仅对已验证预设注入:Codex 支持 Command Code,其他非 Claude
|
||||
* Coding Plan 保持既有行为——
|
||||
* 五个 app 各有一份 OpenCode Go 预设、凭据形态后端全部支持,而智谱/Kimi
|
||||
* 等在其他 app 的自动注入未逐一验证过,不随手扩大
|
||||
* - 所有 app 一视同仁:套餐额度只按 Key(智谱另看 host)查固定端点,与
|
||||
* 客户端协议、base_url 路径无关;凭据提取与后端 `resolve_usage_credentials` 对齐
|
||||
* - ZenMux 例外,仍只在 Claude 注入:它的查询直接 GET 用户填的 base_url,
|
||||
* 其他 app 的推理地址未验证能返回额度
|
||||
* - code 置空:Rust 端走专用 `coding_plan::get_coding_plan_quota`,不执行 JS 脚本
|
||||
*/
|
||||
export function injectCodingPlanUsageScript<
|
||||
@@ -159,15 +173,7 @@ export function injectCodingPlanUsageScript<
|
||||
);
|
||||
const codingPlanProvider = detectCodingPlanProvider(baseUrl);
|
||||
if (!codingPlanProvider) return provider;
|
||||
const isCommandCodeForCodex =
|
||||
appId === "codex" && codingPlanProvider === "command_code";
|
||||
if (
|
||||
appId !== "claude" &&
|
||||
codingPlanProvider !== "opencode_go" &&
|
||||
!isCommandCodeForCodex
|
||||
) {
|
||||
return provider;
|
||||
}
|
||||
if (codingPlanProvider === "zenmux" && appId !== "claude") return provider;
|
||||
|
||||
return {
|
||||
...provider,
|
||||
|
||||
@@ -34,14 +34,16 @@ base_url = "${CODEX_BASE_URL}"`,
|
||||
expect(codex.meta?.usage_script?.codingPlanProvider).toBe("command_code");
|
||||
});
|
||||
|
||||
it("does not extend Command Code into OpenCode", () => {
|
||||
it("injects Command Code into other apps too", () => {
|
||||
const provider = injectCodingPlanUsageScript("opencode", {
|
||||
settingsConfig: {
|
||||
options: { baseURL: CODEX_BASE_URL },
|
||||
},
|
||||
}) as { meta?: { usage_script?: unknown } };
|
||||
}) as { meta?: { usage_script?: { codingPlanProvider?: string } } };
|
||||
|
||||
expect(provider.meta?.usage_script).toBeUndefined();
|
||||
expect(provider.meta?.usage_script?.codingPlanProvider).toBe(
|
||||
"command_code",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not overwrite an existing usage script", () => {
|
||||
|
||||
Reference in new issue
Block a user