





















@@ -1033,6 +1033,24 @@ const isModelPricingKnown = (cost: ReturnType<typeof resolveModelCostConfig>): b
10331033return cost.input > 0 || cost.output > 0 || cost.cacheRead > 0 || cost.cacheWrite > 0;
10341034};
103510351036+type UsageCostResolver = (params: {
1037+provider?: string;
1038+model?: string;
1039+}) => ReturnType<typeof resolveModelCostConfig>;
1040+1041+function createUsageCostResolver(config?: OpenClawConfig): UsageCostResolver {
1042+const cache = new Map<string, ReturnType<typeof resolveModelCostConfig>>();
1043+return ({ provider, model }) => {
1044+const key = `${provider ?? ""}\0${model ?? ""}`;
1045+if (cache.has(key)) {
1046+return cache.get(key);
1047+}
1048+const cost = resolveModelCostConfig({ provider, model, config });
1049+cache.set(key, cost);
1050+return cost;
1051+};
1052+}
1053+10361054async function canReadJsonlFromOffset(filePath: string, startOffset: number): Promise<boolean> {
10371055if (startOffset <= 0) {
10381056return true;
@@ -1092,10 +1110,12 @@ async function* readJsonlRecords(
10921110async function scanTranscriptFile(params: {
10931111filePath: string;
10941112config?: OpenClawConfig;
1113+resolveCost?: UsageCostResolver;
10951114startOffset?: number;
10961115endOffset?: number;
10971116onEntry: (entry: ParsedTranscriptEntry) => void;
10981117}): Promise<void> {
1118+const resolveCost = params.resolveCost ?? createUsageCostResolver(params.config);
10991119for await (const parsed of readJsonlRecords(
11001120params.filePath,
11011121params.startOffset,
@@ -1107,10 +1127,9 @@ async function scanTranscriptFile(params: {
11071127}
1108112811091129if (entry.usage) {
1110-const cost = resolveModelCostConfig({
1130+const cost = resolveCost({
11111131provider: entry.provider,
11121132model: entry.model,
1113-config: params.config,
11141133});
11151134if (cost?.tieredPricing && cost.tieredPricing.length > 0) {
11161135// When tiered pricing is configured, always recompute to override
@@ -1146,13 +1165,15 @@ async function scanTranscriptFile(params: {
11461165async function scanUsageFile(params: {
11471166filePath: string;
11481167config?: OpenClawConfig;
1168+resolveCost?: UsageCostResolver;
11491169startOffset?: number;
11501170endOffset?: number;
11511171onEntry: (entry: ParsedUsageEntry) => void;
11521172}): Promise<void> {
11531173await scanTranscriptFile({
11541174filePath: params.filePath,
11551175config: params.config,
1176+resolveCost: params.resolveCost,
11561177startOffset: params.startOffset,
11571178endOffset: params.endOffset,
11581179onEntry: (entry) => {
@@ -1260,6 +1281,7 @@ export async function loadCostUsageSummary(params?: {
1260128112611282const dailyMap = new Map<string, CostUsageTotals>();
12621283const totals = emptyTotals();
1284+const resolveCost = createUsageCostResolver(params?.config);
1263128512641286const sessionsDir = resolveSessionTranscriptsDirForAgent(params?.agentId);
12651287const entries = await fs.promises.readdir(sessionsDir, { withFileTypes: true }).catch(() => []);
@@ -1286,6 +1308,7 @@ export async function loadCostUsageSummary(params?: {
12861308await scanUsageFile({
12871309 filePath,
12881310config: params?.config,
1311+ resolveCost,
12891312onEntry: (entry) => {
12901313const ts = entry.timestamp?.getTime();
12911314if (!ts || ts < sinceTime || ts > untilTime) {
@@ -1329,6 +1352,7 @@ export async function loadCostUsageSummary(params?: {
13291352async function scanUsageFileForCache(params: {
13301353file: UsageCostTranscriptFile;
13311354config?: OpenClawConfig;
1355+resolveCost?: UsageCostResolver;
13321356previous?: UsageCostCacheFileEntry;
13331357includeSessionSummary?: boolean;
13341358}): Promise<UsageCostCacheFileEntry> {
@@ -1364,6 +1388,7 @@ async function scanUsageFileForCache(params: {
13641388await scanTranscriptFile({
13651389filePath: params.file.filePath,
13661390config: params.config,
1391+resolveCost: params.resolveCost,
13671392 startOffset,
13681393endOffset: params.file.size,
13691394onEntry: (entry) => {
@@ -1519,11 +1544,13 @@ export async function refreshCostUsageCache(params?: {
15191544return aSession - bSession || a.size - b.size || a.filePath.localeCompare(b.filePath);
15201545})
15211546.slice(0, maxFiles);
1547+const resolveCost = createUsageCostResolver(params?.config);
1522154815231549for (const file of staleFiles) {
15241550cache.files[file.filePath] = await scanUsageFileForCache({
15251551 file,
15261552config: params?.config,
1553+ resolveCost,
15271554previous: cache.files[file.filePath],
15281555includeSessionSummary: sessionSummaryFiles.has(file.filePath),
15291556});
@@ -1975,10 +2002,12 @@ export async function loadSessionCostSummary(params: {
19752002const latencyValues: number[] = [];
19762003let lastUserTimestamp: number | undefined;
19772004const MAX_LATENCY_MS = 12 * 60 * 60 * 1000;
2005+const resolveCost = createUsageCostResolver(params.config);
1978200619792007await scanTranscriptFile({
19802008filePath: sessionFile,
19812009config: params.config,
2010+ resolveCost,
19822011onEntry: (entry) => {
19832012const ts = entry.timestamp?.getTime();
19842013@@ -2264,10 +2293,12 @@ export async function loadSessionUsageTimeSeries(params: {
22642293const points: SessionUsageTimePoint[] = [];
22652294let cumulativeTokens = 0;
22662295let cumulativeCost = 0;
2296+const resolveCost = createUsageCostResolver(params.config);
2267229722682298await scanUsageFile({
22692299filePath: sessionFile,
22702300config: params.config,
2301+ resolveCost,
22712302onEntry: (entry) => {
22722303const ts = entry.timestamp?.getTime();
22732304if (!ts) {
@@ -2374,6 +2405,7 @@ export async function loadSessionLogs(params: {
23742405}
23752406}
23762407const limit = params.limit ?? 50;
2408+const resolveCost = createUsageCostResolver(params.config);
2377240923782410for await (const parsed of readJsonlRecords(sessionFile)) {
23792411try {
@@ -2488,10 +2520,9 @@ export async function loadSessionLogs(params: {
24882520if (breakdown?.total !== undefined) {
24892521cost = breakdown.total;
24902522} else {
2491-const costConfig = resolveModelCostConfig({
2523+const costConfig = resolveCost({
24922524provider: message.provider as string | undefined,
24932525model: message.model as string | undefined,
2494-config: params.config,
24952526});
24962527cost = estimateUsageCost({ usage, cost: costConfig });
24972528}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。