diff --git a/internal/agent/agent.go b/internal/agent/agent.go index fb822c3812b391c77a215d7d2895fc8236ae4163..27626fe90292ca7c14db5414571430268b089821 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -172,6 +172,9 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy history, files := a.preparePrompt(msgs, call.Attachments...) + startTime := time.Now() + a.eventPromptSent(call.SessionID) + var currentAssistant *message.Message var shouldSummarize bool result, err := agent.Stream(genCtx, fantasy.AgentStreamCall{ @@ -354,6 +357,9 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy }, }, }) + + a.eventPromptResponded(call.SessionID, time.Since(startTime).Truncate(time.Second)) + if err != nil { isCancelErr := errors.Is(err, context.Canceled) isPermissionErr := errors.Is(err, permission.ErrorPermissionDenied) @@ -684,6 +690,9 @@ func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session, modelConfig.CostPer1MOutCached/1e6*float64(usage.CacheReadTokens) + modelConfig.CostPer1MIn/1e6*float64(usage.InputTokens) + modelConfig.CostPer1MOut/1e6*float64(usage.OutputTokens) + + a.eventTokensUsed(session.ID, model, usage, cost) + session.Cost += cost session.CompletionTokens = usage.OutputTokens + usage.CacheReadTokens session.PromptTokens = usage.InputTokens + usage.CacheCreationTokens diff --git a/internal/agent/event.go b/internal/agent/event.go new file mode 100644 index 0000000000000000000000000000000000000000..87e56e50344240fdd41d0f4740592edfd4e71347 --- /dev/null +++ b/internal/agent/event.go @@ -0,0 +1,50 @@ +package agent + +import ( + "time" + + "charm.land/fantasy" + "github.com/charmbracelet/crush/internal/event" +) + +func (a sessionAgent) eventPromptSent(sessionID string) { + event.PromptSent( + a.eventCommon(sessionID, a.largeModel)..., + ) +} + +func (a sessionAgent) eventPromptResponded(sessionID string, duration time.Duration) { + event.PromptResponded( + append( + a.eventCommon(sessionID, a.largeModel), + "prompt duration pretty", duration.String(), + "prompt duration in seconds", int64(duration.Seconds()), + )..., + ) +} + +func (a sessionAgent) eventTokensUsed(sessionID string, model Model, usage fantasy.Usage, cost float64) { + event.TokensUsed( + append( + a.eventCommon(sessionID, model), + "input tokens", usage.InputTokens, + "output tokens", usage.OutputTokens, + "cache read tokens", usage.CacheReadTokens, + "cache creation tokens", usage.CacheCreationTokens, + "total tokens", usage.InputTokens+usage.OutputTokens+usage.CacheReadTokens+usage.CacheCreationTokens, + "cost", cost, + )..., + ) +} + +func (a sessionAgent) eventCommon(sessionID string, model Model) []any { + m := model.ModelCfg + + return []any{ + "session id", sessionID, + "provider", m.Provider, + "model", m.Model, + "reasoning effort", m.ReasoningEffort, + "thinking mode", m.Think, + } +}