Files
john 4e21ca937a
Deploy Documentation / deploy (push) Has been cancelled
Canary / Prepare Version (push) Has been cancelled
Canary / build-cli (push) Has been cancelled
Canary / Upload Install Script (push) Has been cancelled
Canary / bundle-desktop (push) Has been cancelled
Canary / bundle-desktop-intel (push) Has been cancelled
Canary / bundle-desktop-linux (push) Has been cancelled
Canary / bundle-desktop-windows (push) Has been cancelled
Canary / bundle-desktop-windows-cuda (push) Has been cancelled
Canary / Release (push) Has been cancelled
Unused Dependencies / machete (push) Has been cancelled
CI / changes (push) Has been cancelled
CI / Check Rust Code Format (push) Has been cancelled
CI / Build and Test Rust Project (push) Has been cancelled
CI / Build Rust Project on Windows (push) Has been cancelled
CI / Check MSRV (push) Has been cancelled
CI / Lint Rust Code (push) Has been cancelled
CI / Check Generated Schemas are Up-to-Date (push) Has been cancelled
CI / Test and Lint Electron Desktop App (push) Has been cancelled
CI / H5 Plaza Tests and Build (push) Has been cancelled
Live Provider Tests / check-fork (push) Has been cancelled
Live Provider Tests / changes (push) Has been cancelled
Live Provider Tests / Build Binary (push) Has been cancelled
Live Provider Tests / Smoke Tests (push) Has been cancelled
Live Provider Tests / Smoke Tests (Code Execution) (push) Has been cancelled
Live Provider Tests / Compaction Tests (push) Has been cancelled
Live Provider Tests / goose server HTTP integration tests (push) Has been cancelled
Publish Ask AI Bot Docker Image / docker (push) Has been cancelled
Publish Docker Image / docker (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Add TKMind platform extensions, H5/MindSpace stack, and deployment tooling.
Fork goose with custom MCP widgets, platform extensions (aider, git, web, search),
MindSpace H5 backend/frontend, Plaza/Ops UIs, and deploy scripts for tkmind.cn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 21:30:20 +08:00

67 lines
2.6 KiB
JavaScript

export function loadBillingConfig() {
const useBackendCost = process.env.H5_USE_BACKEND_COST !== '0';
return {
useBackendCost,
usdCnyRate: Number(process.env.H5_USD_CNY_RATE ?? 7.2),
inputCentsPer1k: Number(process.env.H5_BILL_INPUT_CENTS_PER_1K ?? 2),
outputCentsPer1k: Number(process.env.H5_BILL_OUTPUT_CENTS_PER_1K ?? 6),
minBillCents: Number(process.env.H5_MIN_BILL_CENTS ?? 1),
};
}
export function normalizeTokenState(raw) {
if (!raw || typeof raw !== 'object') {
return {
inputTokens: 0,
outputTokens: 0,
totalTokens: 0,
accumulatedInputTokens: 0,
accumulatedOutputTokens: 0,
accumulatedTotalTokens: 0,
accumulatedCost: null,
};
}
return {
inputTokens: Number(raw.inputTokens ?? raw.input_tokens ?? 0),
outputTokens: Number(raw.outputTokens ?? raw.output_tokens ?? 0),
totalTokens: Number(raw.totalTokens ?? raw.total_tokens ?? 0),
accumulatedInputTokens: Number(
raw.accumulatedInputTokens ?? raw.accumulated_input_tokens ?? raw.inputTokens ?? 0,
),
accumulatedOutputTokens: Number(
raw.accumulatedOutputTokens ?? raw.accumulated_output_tokens ?? raw.outputTokens ?? 0,
),
accumulatedTotalTokens: Number(
raw.accumulatedTotalTokens ?? raw.accumulated_total_tokens ?? raw.totalTokens ?? 0,
),
accumulatedCost:
raw.accumulatedCost ?? raw.accumulated_cost ?? null,
};
}
export function computeDeltaCostCents(previous, current, config = loadBillingConfig()) {
const prevCost =
previous?.lastAccumulatedCost == null ? null : Number(previous.lastAccumulatedCost);
const currCost =
current.accumulatedCost == null ? null : Number(current.accumulatedCost);
if (config.useBackendCost && prevCost != null && currCost != null && currCost >= prevCost) {
const deltaUsd = currCost - prevCost;
return Math.max(config.minBillCents, Math.ceil(deltaUsd * config.usdCnyRate * 100));
}
if (config.useBackendCost && prevCost == null && currCost != null && currCost > 0) {
return Math.max(config.minBillCents, Math.ceil(currCost * config.usdCnyRate * 100));
}
const prevIn = Number(previous?.lastInputTokens ?? 0);
const prevOut = Number(previous?.lastOutputTokens ?? 0);
const deltaIn = Math.max(0, current.accumulatedInputTokens - prevIn);
const deltaOut = Math.max(0, current.accumulatedOutputTokens - prevOut);
if (deltaIn === 0 && deltaOut === 0) return 0;
const raw =
(deltaIn / 1000) * config.inputCentsPer1k + (deltaOut / 1000) * config.outputCentsPer1k;
if (raw <= 0) return 0;
return Math.max(config.minBillCents, Math.ceil(raw));
}