File size: 1,496 Bytes
68d7816
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
47
48
49
50
import { modelKey, type LlmModel } from '#/llm/model';
import { emptyUsage, type TokenUsage } from '#/llm/usage';

export interface UsageRecord {
  usage: Partial<TokenUsage>;
  model?: LlmModel;
  turnId?: number;
  at: number;
}

export interface UsageSummary {
  total: TokenUsage;
  byModel: Record<string, TokenUsage>;
  byTurn: Record<number, TokenUsage>;
}

export function emptyUsageSummary(): UsageSummary {
  return { total: emptyUsage(), byModel: {}, byTurn: {} };
}

function addUsage(base: TokenUsage | undefined, usage: Partial<TokenUsage>): TokenUsage {
  const next = base ?? emptyUsage();
  return {
    inputOther: next.inputOther + (usage.inputOther ?? 0),
    output: next.output + (usage.output ?? 0),
    inputCacheRead: next.inputCacheRead + (usage.inputCacheRead ?? 0),
    inputCacheCreation: next.inputCacheCreation + (usage.inputCacheCreation ?? 0),
  };
}

export function accumulateUsage(summary: UsageSummary, record: UsageRecord): UsageSummary {
  return {
    total: addUsage(summary.total, record.usage),
    byModel:
      record.model === undefined
        ? summary.byModel
        : {
            ...summary.byModel,
            [modelKey(record.model)]: addUsage(
              summary.byModel[modelKey(record.model)],
              record.usage,
            ),
          },
    byTurn:
      record.turnId === undefined
        ? summary.byTurn
        : { ...summary.byTurn, [record.turnId]: addUsage(summary.byTurn[record.turnId], record.usage) },
  };
}