@@ -34,6 +34,38 @@ export const RequestLogsRow: FC<RequestLogsRowProps> = ({ interception }) => {
3434( acc , tokenUsage ) => acc + tokenUsage . output_tokens ,
35350 ,
3636) ;
37+
38+ const KEY_ANTHROPIC_READ = "cache_read_input" ;
39+ const KEY_ANTHROPIC_WRITTEN = "cache_creation_input" ;
40+
41+ const KEY_OPENAI_READ = "prompt_cached" ;
42+
43+ // These are an unstructured metadata field of "Record<string, unknown>",
44+ // so we need to check if they're numbers and if not, return 0.
45+ const cachedReadTokens = interception . token_usages . reduce (
46+ ( acc , tokenUsage ) =>
47+ acc +
48+ ( interception . provider === "anthropic"
49+ ?typeof tokenUsage . metadata ?. [ KEY_ANTHROPIC_READ ] === "number"
50+ ?tokenUsage . metadata ?. [ KEY_ANTHROPIC_READ ]
51+ :0
52+ :typeof tokenUsage . metadata ?. [ KEY_OPENAI_READ ] === "number"
53+ ?tokenUsage . metadata ?. [ KEY_OPENAI_READ ]
54+ :0 ) ,
55+ 0 ,
56+ ) ;
57+ const cachedWrittenTokens = interception . token_usages . reduce (
58+ ( acc , tokenUsage ) =>
59+ acc +
60+ ( interception . provider === "anthropic"
61+ ?typeof tokenUsage . metadata ?. [ KEY_ANTHROPIC_WRITTEN ] === "number"
62+ ?tokenUsage . metadata ?. [ KEY_ANTHROPIC_WRITTEN ]
63+ :0
64+ :// OpenAI doesn't have a cached written tokens field, so we return 0.
65+ 0 ) ,
66+ 0 ,
67+ ) ;
68+
3769const toolCalls = interception . tool_usages . length ;
3870const duration =
3971interception . ended_at &&
@@ -154,6 +186,12 @@ export const RequestLogsRow: FC<RequestLogsRowProps> = ({ interception }) => {
154186< dt > Output Tokens:</ dt >
155187< dd data-chromatic = "ignore" > { outputTokens } </ dd >
156188
189+ < dt > Cached Read Tokens:</ dt >
190+ < dd data-chromatic = "ignore" > { cachedReadTokens } </ dd >
191+
192+ < dt > Cached Written Tokens:</ dt >
193+ < dd data-chromatic = "ignore" > { cachedWrittenTokens } </ dd >
194+
157195< dt > Tool Calls:</ dt >
158196< dd data-chromatic = "ignore" >
159197{ interception . tool_usages . length }