Spaces:
Running
Running
File size: 1,711 Bytes
c7d34c1 b1cfe1b c7d34c1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | import { NewApiCostResolver } from './new-api';
import type { ActualCostDetails, ResolveActualCostInput, UpstreamCostProvider } from './types';
export type { ActualCostDetails, ActualCostConfidence, ActualCostSource, UpstreamCostProvider } from './types';
function unavailable(reason: string, upstreamProvider: UpstreamCostProvider = 'unknown'): ActualCostDetails {
return {
currency: 'usd-equivalent',
source: 'unavailable',
confidence: 'none',
upstreamProvider,
reason
};
}
function detectKnownProvider(apiBaseUrl: string): UpstreamCostProvider {
let upstreamProvider: UpstreamCostProvider = 'unknown';
try {
const parsed = new URL(apiBaseUrl);
const pathIsOpenAiApiRoot =
parsed.pathname === '/' || parsed.pathname === '/v1' || parsed.pathname.startsWith('/v1/');
if (parsed.protocol === 'https:' && parsed.hostname === 'api.openai.com' && pathIsOpenAiApiRoot) {
upstreamProvider = 'openai';
}
} catch (error) {
console.debug('解析上游 API URL 失败。', { apiBaseUrl, error });
if (!(error instanceof TypeError)) {
throw error;
}
}
return upstreamProvider;
}
export async function resolveActualCost(input: ResolveActualCostInput): Promise<ActualCostDetails> {
if (!input.apiBaseUrl || !input.apiKey) {
return unavailable('缺少上游 API URL 或 API key。');
}
const knownProvider = detectKnownProvider(input.apiBaseUrl);
if (knownProvider === 'openai') {
return unavailable('OpenAI 官方接口不提供 new-api 扣费日志。', 'openai');
}
return new NewApiCostResolver().resolve(input);
}
|