Merge remote-tracking branch 'origin/farm/260d1f69/fix-alibaba-cn-quota-reporting'

This commit is contained in:
can1357
2026-08-14 07:19:24 +02:00
5 changed files with 187 additions and 38 deletions
+1
View File
@@ -5,6 +5,7 @@
### Fixed
- Fixed `omp usage invalidate` to discard stale OAuth and API-key usage snapshots, then force a cache-bypassing, per-provider serialized refresh so upgraded subscriptions do not silently retain pre-change quota data.
- Fixed quota reporting and Cookie capture guidance for China (Beijing) Alibaba Token Plan credentials ([#8509](https://github.com/can1357/oh-my-pi/issues/8509)).
## [17.3.3] - 2026-08-14
@@ -86,9 +86,13 @@ export async function loginAlibabaTokenPlan(options: OAuthController): Promise<s
fetch: options.fetch,
});
const cookieRequestHost =
baseUrl === ALIBABA_TOKEN_PLAN_CN_BASE_URL ? "bailian-cs.console.aliyun.com" : "cs-data.qwencloud.com";
const rawCookie = await options.onPrompt({
message:
"Optional quota reporting: open browser DevTools → Network, reload the Token Plan page, filter for api.json, and select the cs-data.qwencloud.com/data/api.json request whose api query ends in /tokenplan/personal/api/v2/usage. Copy Request Headers → Cookie, then paste the complete name=value; ... value here, or press Enter to skip.",
baseUrl === ALIBABA_TOKEN_PLAN_CN_BASE_URL
? "Optional quota reporting: open browser DevTools → Network, reload the Token Plan page, filter for api.json, and select the bailian-cs.console.aliyun.com/data/api.json request whose api query ends in /tokenplan/personal/api/v2/usage. Copy Request Headers → Cookie, then paste the complete name=value; ... value here, or press Enter to skip."
: "Optional quota reporting: open browser DevTools → Network, reload the Token Plan page, filter for api.json, and select the cs-data.qwencloud.com/data/api.json request whose api query ends in /tokenplan/personal/api/v2/usage. Copy Request Headers → Cookie, then paste the complete name=value; ... value here, or press Enter to skip.",
placeholder: "name=value; name=value; ...",
allowEmpty: true,
});
@@ -107,7 +111,7 @@ export async function loginAlibabaTokenPlan(options: OAuthController): Promise<s
})
) {
throw new AIError.ConfigurationError(
"Invalid QwenCloud Cookie header. Copy the complete Cookie request header from the cs-data.qwencloud.com usage request, not a single cookie value.",
`Invalid QwenCloud Cookie header. Copy the complete Cookie request header from the ${cookieRequestHost} usage request, not a single cookie value.`,
);
}
+89 -34
View File
@@ -1,5 +1,8 @@
import { toNumber } from "@oh-my-pi/pi-catalog/utils";
import { parseAlibabaTokenPlanCredential } from "@oh-my-pi/pi-catalog/wire/alibaba-token-plan";
import {
ALIBABA_TOKEN_PLAN_CN_BASE_URL,
parseAlibabaTokenPlanCredential,
} from "@oh-my-pi/pi-catalog/wire/alibaba-token-plan";
import type {
CredentialRankingStrategy,
UsageFetchContext,
@@ -12,21 +15,45 @@ import { isRecord } from "../utils";
import { HOUR_MS, parsePositiveTimestamp, WEEK_MS } from "./shared";
const PROVIDER = "alibaba-token-plan";
const CONSOLE_ORIGIN = "https://home.qwencloud.com";
const DASHBOARD_URL = `${CONSOLE_ORIGIN}/billing/subscription/token-plan-individual`;
const USER_INFO_URL = `${CONSOLE_ORIGIN}/tool/user/info.json`;
const GATEWAY_ACTION = "IntlBroadScopeAspnGateway";
const USAGE_API = "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/usage";
const USAGE_URL = `https://cs-data.qwencloud.com/data/api.json?product=sfm_bailian&action=${GATEWAY_ACTION}&api=${encodeURIComponent(USAGE_API)}`;
const BROWSER_USER_AGENT =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36";
const CONSOLE_CORNERSTONE_PARAM = {
domain: "home.qwencloud.com",
consoleSite: "QWENCLOUD",
console: "ONE_CONSOLE",
xsp_lang: "en-US",
protocol: "V2",
productCode: "p_efm",
const INTERNATIONAL_CONSOLE = {
origin: "https://home.qwencloud.com",
dashboardUrl: "https://home.qwencloud.com/billing/subscription/token-plan-individual",
sessionUrl: "https://home.qwencloud.com/tool/user/info.json",
gatewayAction: "IntlBroadScopeAspnGateway",
region: "ap-southeast-1",
usageUrl: `https://cs-data.qwencloud.com/data/api.json?product=sfm_bailian&action=IntlBroadScopeAspnGateway&api=${encodeURIComponent(USAGE_API)}`,
cornerstoneParam: {
domain: "home.qwencloud.com",
consoleSite: "QWENCLOUD",
console: "ONE_CONSOLE",
xsp_lang: "en-US",
protocol: "V2",
productCode: "p_efm",
},
} as const;
const CHINA_CONSOLE = {
origin: "https://bailian.console.aliyun.com",
dashboardUrl: "https://bailian.console.aliyun.com/cn-beijing?tab=plan",
sessionUrl: "https://bailian.console.aliyun.com/cn-beijing?tab=plan",
gatewayAction: "BroadScopeAspnGateway",
region: "cn-beijing",
usageUrl: `https://bailian-cs.console.aliyun.com/data/api.json?action=BroadScopeAspnGateway&product=sfm_bailian&api=${encodeURIComponent(USAGE_API)}`,
cornerstoneParam: {
feURL: "https://bailian.console.aliyun.com/cn-beijing?tab=plan#/efm/subscription/token-plan/personal",
protocol: "V2",
console: "ONE_CONSOLE",
productCode: "p_efm",
switchAgent: 12608464,
switchUserType: 3,
domain: "bailian.console.aliyun.com",
consoleSite: "BAILIAN_ALIYUN",
userNickName: "",
userPrincipalName: "",
xsp_lang: "zh-CN",
},
} as const;
function extractCookieValue(header: string, name: string): string | undefined {
@@ -102,35 +129,56 @@ async function fetchAlibabaTokenPlanUsage(
const credential = parseAlibabaTokenPlanCredential(params.credential.apiKey);
if (!credential?.cookie) return null;
const cookie = credential.cookie;
const isChina = credential.baseUrl === ALIBABA_TOKEN_PLAN_CN_BASE_URL;
const consoleConfig = isChina ? CHINA_CONSOLE : INTERNATIONAL_CONSOLE;
try {
const userResponse = await ctx.fetch(USER_INFO_URL, {
const sessionResponse = await ctx.fetch(consoleConfig.sessionUrl, {
headers: {
Accept: "application/json, text/plain, */*",
Accept: isChina
? "text/html,application/xhtml+xml,application/json;q=0.9,*/*;q=0.8"
: "application/json, text/plain, */*",
Cookie: cookie,
Referer: `${CONSOLE_ORIGIN}/`,
Referer: `${consoleConfig.origin}/`,
"User-Agent": BROWSER_USER_AGENT,
},
redirect: "manual",
signal: params.signal,
});
if (!userResponse.ok) {
ctx.logger?.warn("QwenCloud session lookup failed", { provider: PROVIDER, status: userResponse.status });
if (!sessionResponse.ok) {
ctx.logger?.warn("Alibaba Token Plan session lookup failed", {
provider: PROVIDER,
status: sessionResponse.status,
});
return null;
}
const userPayload: unknown = await userResponse.json();
if (!isRecord(userPayload) || !isRecord(userPayload.data) || typeof userPayload.data.secToken !== "string") {
ctx.logger?.warn("QwenCloud session response invalid", { provider: PROVIDER });
return null;
let secToken: string | undefined;
let accountId: string | undefined;
if (isChina) {
const html = await sessionResponse.text();
secToken = /\bSEC_TOKEN\s*:\s*"([^"]+)"/.exec(html)?.[1];
if (!secToken) {
ctx.logger?.warn("Alibaba Token Plan China session response invalid", { provider: PROVIDER });
return null;
}
} else {
const userPayload: unknown = await sessionResponse.json();
if (!isRecord(userPayload) || !isRecord(userPayload.data) || typeof userPayload.data.secToken !== "string") {
ctx.logger?.warn("QwenCloud session response invalid", { provider: PROVIDER });
return null;
}
secToken = userPayload.data.secToken;
accountId = accountIdFromUserData(userPayload.data);
}
const secToken = userPayload.data.secToken;
const csrf = extractCookieValue(cookie, "login_aliyunid_csrf") ?? extractCookieValue(cookie, "csrf");
const headers: Record<string, string> = {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/x-www-form-urlencoded",
Cookie: cookie,
Origin: CONSOLE_ORIGIN,
Referer: DASHBOARD_URL,
Origin: consoleConfig.origin,
Referer: consoleConfig.dashboardUrl,
"User-Agent": BROWSER_USER_AGENT,
"X-Requested-With": "XMLHttpRequest",
};
@@ -140,16 +188,21 @@ async function fetchAlibabaTokenPlanUsage(
}
const body = new URLSearchParams({
product: "sfm_bailian",
action: GATEWAY_ACTION,
region: "ap-southeast-1",
action: consoleConfig.gatewayAction,
region: consoleConfig.region,
sec_token: secToken,
params: JSON.stringify({
Api: USAGE_API,
Data: { cornerstoneParam: CONSOLE_CORNERSTONE_PARAM },
Data: {
cornerstoneParam: {
...(isChina ? { feTraceId: crypto.randomUUID() } : {}),
...consoleConfig.cornerstoneParam,
},
},
V: "1.0",
}),
});
const usageResponse = await ctx.fetch(USAGE_URL, {
const usageResponse = await ctx.fetch(consoleConfig.usageUrl, {
method: "POST",
headers,
body,
@@ -157,16 +210,18 @@ async function fetchAlibabaTokenPlanUsage(
signal: params.signal,
});
if (!usageResponse.ok) {
ctx.logger?.warn("QwenCloud usage fetch failed", { provider: PROVIDER, status: usageResponse.status });
ctx.logger?.warn("Alibaba Token Plan usage fetch failed", {
provider: PROVIDER,
status: usageResponse.status,
});
return null;
}
const payload: unknown = await usageResponse.json();
if (!isRecord(payload) || payload.successResponse === false || !isRecord(payload.data)) {
ctx.logger?.warn("QwenCloud usage response invalid", { provider: PROVIDER });
ctx.logger?.warn("Alibaba Token Plan usage response invalid", { provider: PROVIDER });
return null;
}
const responseData = unwrapGatewayData(payload.data);
const accountId = accountIdFromUserData(userPayload.data);
const limits = [
buildLimit(
"5h",
@@ -190,10 +245,10 @@ async function fetchAlibabaTokenPlanUsage(
provider: PROVIDER,
fetchedAt: Date.now(),
limits,
metadata: { source: "qwencloud-console", ...(accountId ? { accountId } : {}) },
metadata: { source: isChina ? "bailian-console" : "qwencloud-console", ...(accountId ? { accountId } : {}) },
};
} catch (error) {
ctx.logger?.warn("QwenCloud usage request failed", {
ctx.logger?.warn("Alibaba Token Plan usage request failed", {
provider: PROVIDER,
error: error instanceof Error ? error.name : "unknown",
});
@@ -5,7 +5,10 @@ import {
alibabaTokenPlanRankingStrategy,
alibabaTokenPlanUsageProvider,
} from "@oh-my-pi/pi-ai/usage/alibaba-token-plan";
import { serializeAlibabaTokenPlanCredential } from "@oh-my-pi/pi-catalog/wire/alibaba-token-plan";
import {
ALIBABA_TOKEN_PLAN_CN_BASE_URL,
serializeAlibabaTokenPlanCredential,
} from "@oh-my-pi/pi-catalog/wire/alibaba-token-plan";
function params(apiKey: string): UsageFetchParams {
return {
@@ -102,6 +105,84 @@ describe("QwenCloud Token Plan opt-in usage", () => {
expect(windows.secondary?.id).toBe("credits:7d");
});
test("fetches China quota through the Beijing console gateway", async () => {
const requests: { url: string; init?: RequestInit }[] = [];
const fetchMock: FetchImpl = (input, init) => {
requests.push({ url: String(input), init });
if (requests.length === 1) {
return Promise.resolve(
new Response('<script>window.ALIYUN_CONSOLE_CONFIG = { SEC_TOKEN: "cn-sec-token" };</script>'),
);
}
return Promise.resolve(
Response.json({
code: "200",
data: {
DataV2: {
data: {
data: {
per1WeekPercentage: 0.7913113,
per1WeekResetTime: 1_786_716_480_000,
},
},
},
},
successResponse: true,
}),
);
};
const cookie = "login_aliyunid_csrf=cn-csrf; aliyun_lang=zh";
const credential = serializeAlibabaTokenPlanCredential("sk-sp-beijing", cookie, ALIBABA_TOKEN_PLAN_CN_BASE_URL);
const report = await alibabaTokenPlanUsageProvider.fetchUsage(params(credential), { fetch: fetchMock });
expect(requests).toHaveLength(2);
expect(requests[0]?.url).toBe("https://bailian.console.aliyun.com/cn-beijing?tab=plan");
expect(new Headers(requests[0]?.init?.headers).get("Cookie")).toBe(cookie);
expect(requests[1]?.url).toBe(
"https://bailian-cs.console.aliyun.com/data/api.json?action=BroadScopeAspnGateway&product=sfm_bailian&api=zeldaHttp.apikeyMgr.%2Ftokenplan%2Fpersonal%2Fapi%2Fv2%2Fusage",
);
const usageHeaders = new Headers(requests[1]?.init?.headers);
expect(usageHeaders.get("Origin")).toBe("https://bailian.console.aliyun.com");
expect(usageHeaders.get("Referer")).toBe("https://bailian.console.aliyun.com/cn-beijing?tab=plan");
const body = new URLSearchParams(String(requests[1]?.init?.body));
expect(body.get("action")).toBe("BroadScopeAspnGateway");
expect(body.get("region")).toBe("cn-beijing");
expect(body.get("sec_token")).toBe("cn-sec-token");
const gatewayParams: unknown = JSON.parse(body.get("params") ?? "null");
expect(gatewayParams).toMatchObject({
Api: "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/usage",
Data: {
cornerstoneParam: {
feTraceId: expect.any(String),
feURL: "https://bailian.console.aliyun.com/cn-beijing?tab=plan#/efm/subscription/token-plan/personal",
protocol: "V2",
console: "ONE_CONSOLE",
productCode: "p_efm",
switchAgent: 12608464,
switchUserType: 3,
domain: "bailian.console.aliyun.com",
consoleSite: "BAILIAN_ALIYUN",
userNickName: "",
userPrincipalName: "",
xsp_lang: "zh-CN",
},
},
V: "1.0",
});
expect(report).toMatchObject({
provider: "alibaba-token-plan",
limits: [
{
id: "credits:7d",
window: { id: "7d", durationMs: 604_800_000, resetsAt: 1_786_716_480_000 },
amount: { usedFraction: 0.7913113, unit: "percent" },
},
],
});
expect(report?.limits).toHaveLength(1);
});
test("does not claim quota support for API-key-only credentials", async () => {
let fetched = false;
const fetchMock: FetchImpl = () => {
+9 -1
View File
@@ -36,10 +36,17 @@ describe("QwenCloud Token Plan login", () => {
test("China (Beijing) region validates against and routes inference to cn-beijing", async () => {
const authRequests: { url: string; instructions?: string }[] = [];
let requestedUrl = "";
let cookiePrompt = "";
const prompts = ["2", "sk-sp-beijing"];
const credential = await loginAlibabaTokenPlan({
onAuth: request => authRequests.push(request),
onPrompt: async prompt => (prompt.allowEmpty ? "" : (prompts.shift() ?? "")),
onPrompt: async prompt => {
if (prompt.allowEmpty) {
cookiePrompt = prompt.message;
return "";
}
return prompts.shift() ?? "";
},
fetch: input => {
requestedUrl = String(input);
return Promise.resolve(Response.json({ data: [{ id: "qwen3.7-plus" }] }));
@@ -48,6 +55,7 @@ describe("QwenCloud Token Plan login", () => {
expect(requestedUrl).toBe("https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1/models");
expect(authRequests[0]?.url).toBe("https://www.aliyun.com/benefit/scene/tokenplan");
expect(cookiePrompt).toContain("bailian-cs.console.aliyun.com/data/api.json");
expect(JSON.parse(credential)).toEqual({
token: "sk-sp-beijing",
baseUrl: "https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",