Report token usage on each message end

Why: the direct-path adapter accounts usage per turn, including runs that stop on a budget error before the final usage event.
Evidence: go test ./runtime/ ./runtime/llm/ after the field was added.
Impact: message_end and usage events carry TotalTokens. Callers that ignore the new field are unchanged.
Refs: feature/agent-harness-p1
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-01 13:25:58 +00:00
co-authored by Cursor
parent 35f65a3c49
commit e2815bbf94
+5 -3
View File
@@ -36,9 +36,11 @@ type Event struct {
// Detail carries tool arguments/results or reasoning deltas for
// process-visualization consumers; log writers may ignore it.
Detail string
// PromptTokens / CompletionTokens 只在 type=usage 时有意义。
// PromptTokens / CompletionTokens / TotalTokens 在 type=usage 或
// type=message_end 时有意义,供调用方累计用量。
PromptTokens int
CompletionTokens int
TotalTokens int
}
// Config drives one agent session.
@@ -184,7 +186,7 @@ func Run(ctx context.Context, cfg Config, user llm.Message) (Result, error) {
return Result{}, err
}
messages = append(messages, last)
emit(cfg, Event{Type: "message_end", Message: last})
emit(cfg, Event{Type: "message_end", Message: last, PromptTokens: end.Usage.PromptTokens, CompletionTokens: end.Usage.CompletionTokens, TotalTokens: end.Usage.TotalTokens})
if last.StopReason == llm.StopToolCalls && len(last.ToolCalls) > 0 {
if cfg.Budget != nil && cfg.Budget.MaxToolCalls > 0 && toolCalls+len(last.ToolCalls) > cfg.Budget.MaxToolCalls {
@@ -491,7 +493,7 @@ func drain(fn func() []llm.Message) []llm.Message {
}
func emitUsage(cfg Config, usage llm.Usage) {
emit(cfg, Event{Type: "usage", PromptTokens: usage.PromptTokens, CompletionTokens: usage.CompletionTokens})
emit(cfg, Event{Type: "usage", PromptTokens: usage.PromptTokens, CompletionTokens: usage.CompletionTokens, TotalTokens: usage.TotalTokens})
}
func emit(cfg Config, ev Event) {