Skip to content

Commit f5ac92a

Browse files
committed
feat(core,webapp): expose cached cost on the run span API
The span API ai object now returns cachedCost and cacheCreationCost alongside inputCost/outputCost/totalCost. Since inputCost covers only the non-cached input, these fields let consumers reconstruct the full cost breakdown for prompt-cached calls instead of seeing an unexplained gap below totalCost.
1 parent ccacbb8 commit f5ac92a

7 files changed

Lines changed: 17 additions & 0 deletions

File tree

.changeset/span-api-cached-cost.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/core": patch
3+
---
4+
5+
The run span API response now includes `cachedCost` and `cacheCreationCost` on the `ai` object, alongside the existing `inputCost` / `outputCost` / `totalCost`. `inputCost` reflects only the non-cached input, so these fields let you reconstruct the full cost breakdown for prompt-cached calls.

apps/webapp/app/components/runs/v3/ai/extractAISpanData.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ export function extractAISpanData(
110110
inputCost: num(triggerLlm.input_cost),
111111
outputCost: num(triggerLlm.output_cost),
112112
totalCost: num(triggerLlm.total_cost),
113+
cachedCost: num(triggerLlm.cached_cost),
114+
cacheCreationCost: num(triggerLlm.cache_creation_cost),
113115
responseText: isV7
114116
? extractGenAiAssistantText(gOutput.messages) || undefined
115117
: str(aiResponse.text) || undefined,

apps/webapp/app/components/runs/v3/ai/extractAISummarySpanData.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ export function extractAISummarySpanData(
108108
inputCost: num(triggerLlm.input_cost),
109109
outputCost: num(triggerLlm.output_cost),
110110
totalCost: num(triggerLlm.total_cost),
111+
cachedCost: num(triggerLlm.cached_cost),
112+
cacheCreationCost: num(triggerLlm.cache_creation_cost),
111113
responseText: str(aiResponse.text) || undefined,
112114
responseObject: str(aiResponse.object) || undefined,
113115
toolDefinitions: undefined,

apps/webapp/app/components/runs/v3/ai/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ export type AISpanData = {
104104
inputCost?: number;
105105
outputCost?: number;
106106
totalCost?: number;
107+
cachedCost?: number;
108+
cacheCreationCost?: number;
107109

108110
// Response text (final assistant output)
109111
responseText?: string;

apps/webapp/app/routes/api.v1.runs.$runId.spans.$spanId.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ export const loader = createLoaderApiRoute(
170170
inputCost: aiData.inputCost,
171171
outputCost: aiData.outputCost,
172172
totalCost: aiData.totalCost,
173+
cachedCost: aiData.cachedCost,
174+
cacheCreationCost: aiData.cacheCreationCost,
173175
tokensPerSecond: aiData.tokensPerSecond,
174176
msToFirstChunk: aiData.msToFirstChunk,
175177
durationMs: aiData.durationMs,

apps/webapp/app/v3/utils/enrichCreatableEvents.server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ function enrichLlmMetrics(event: CreateEventInput): void {
110110
"trigger.llm.input_cost": cost.inputCost,
111111
"trigger.llm.output_cost": cost.outputCost,
112112
"trigger.llm.total_cost": cost.totalCost,
113+
"trigger.llm.cached_cost": cost.costDetails["input_cached_tokens"] ?? 0,
114+
"trigger.llm.cache_creation_cost": cost.costDetails["cache_creation_input_tokens"] ?? 0,
113115
"trigger.llm.matched_model": cost.matchedModelName,
114116
"trigger.llm.matched_model_id": cost.matchedModelId,
115117
"trigger.llm.pricing_tier": cost.pricingTierName,

packages/core/src/v3/schemas/api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,6 +1993,8 @@ export const RetrieveSpanDetailResponseBody = z.object({
19931993
inputCost: z.number().optional(),
19941994
outputCost: z.number().optional(),
19951995
totalCost: z.number().optional(),
1996+
cachedCost: z.number().optional(),
1997+
cacheCreationCost: z.number().optional(),
19961998
tokensPerSecond: z.number().optional(),
19971999
msToFirstChunk: z.number().optional(),
19982000
durationMs: z.number(),

0 commit comments

Comments
 (0)