persist usage/cost data across session restarts
This commit is contained in:
parent
95557b35ab
commit
d903980256
|
|
@ -411,10 +411,7 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
|||
s.emit(infoEvent(fmt.Sprintf("error: %v", err)))
|
||||
return
|
||||
}
|
||||
s.session = RestoreSession(ps.Messages)
|
||||
if ps.TaskState != nil {
|
||||
s.session.TaskState = ps.TaskState
|
||||
}
|
||||
s.session = RestoreSession(&ps)
|
||||
s.emit(infoEvent(fmt.Sprintf("resumed session %s (%d messages)", name, len(ps.Messages))))
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -2177,7 +2177,7 @@ func TestRestoreSession_RoundTrip(t *testing.T) {
|
|||
t.Errorf("ps.ID=%q ps.Agent=%q", ps.ID, ps.Agent)
|
||||
}
|
||||
|
||||
restored := RestoreSession(ps.Messages)
|
||||
restored := RestoreSession(&ps)
|
||||
if restored.goal != "first user message" {
|
||||
t.Errorf("goal = %q; want %q", restored.goal, "first user message")
|
||||
}
|
||||
|
|
@ -2192,7 +2192,7 @@ func TestRestoreSession_GoalFromFirstUserMessage(t *testing.T) {
|
|||
{Role: "user", Content: "the real goal"},
|
||||
{Role: "user", Content: "second user msg"},
|
||||
}
|
||||
s := RestoreSession(msgs)
|
||||
s := RestoreSession(&PersistedSession{Messages: msgs})
|
||||
if s.goal != "the real goal" {
|
||||
t.Errorf("goal = %q; want %q", s.goal, "the real goal")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,15 @@ type PersistedSession struct {
|
|||
Remote string `json:"remote,omitempty"`
|
||||
Messages []backend.Message `json:"messages"`
|
||||
TaskState *TaskState `json:"taskState,omitempty"`
|
||||
// Usage and cost tracking, persisted across restarts.
|
||||
TotalInputTokens int `json:"totalInputTokens,omitempty"`
|
||||
TotalCachedInputTokens int `json:"totalCachedInputTokens,omitempty"`
|
||||
TotalCacheCreationTokens int `json:"totalCacheCreationTokens,omitempty"`
|
||||
TotalOutputTokens int `json:"totalOutputTokens,omitempty"`
|
||||
TotalRequests int `json:"totalRequests,omitempty"`
|
||||
Estimated bool `json:"estimated,omitempty"`
|
||||
LastTurnCostUSD float64 `json:"lastTurnCostUSD,omitempty"`
|
||||
SessionCostUSD float64 `json:"sessionCostUSD,omitempty"`
|
||||
}
|
||||
|
||||
// TaskState is a compact structured overlay that summarizes the agent's
|
||||
|
|
@ -92,14 +101,22 @@ func (s *Session) saveTo(path, id, agentName, cwd string) error {
|
|||
// saveToFull writes session state including backend/model info.
|
||||
func (s *Session) saveToFull(path, id, agentName, backendName, modelName, cwd, remote string) error {
|
||||
ps := PersistedSession{
|
||||
ID: id,
|
||||
Agent: agentName,
|
||||
Backend: backendName,
|
||||
Model: modelName,
|
||||
CWD: cwd,
|
||||
Remote: remote,
|
||||
Messages: s.messages,
|
||||
TaskState: s.TaskState,
|
||||
ID: id,
|
||||
Agent: agentName,
|
||||
Backend: backendName,
|
||||
Model: modelName,
|
||||
CWD: cwd,
|
||||
Remote: remote,
|
||||
Messages: s.messages,
|
||||
TaskState: s.TaskState,
|
||||
TotalInputTokens: s.TotalInputTokens,
|
||||
TotalCachedInputTokens: s.TotalCachedInputTokens,
|
||||
TotalCacheCreationTokens: s.TotalCacheCreationTokens,
|
||||
TotalOutputTokens: s.TotalOutputTokens,
|
||||
TotalRequests: s.TotalRequests,
|
||||
Estimated: s.Estimated,
|
||||
LastTurnCostUSD: s.LastTurnCostUSD,
|
||||
SessionCostUSD: s.SessionCostUSD,
|
||||
}
|
||||
data, err := json.Marshal(ps)
|
||||
if err != nil {
|
||||
|
|
@ -122,9 +139,20 @@ func LoadPersistedSession(path string) (*PersistedSession, error) {
|
|||
}
|
||||
|
||||
// RestoreSession reconstructs a Session from a persisted message list.
|
||||
func RestoreSession(messages []backend.Message) *Session {
|
||||
s := &Session{messages: messages}
|
||||
for _, m := range messages {
|
||||
func RestoreSession(ps *PersistedSession) *Session {
|
||||
s := &Session{
|
||||
messages: ps.Messages,
|
||||
TaskState: ps.TaskState,
|
||||
TotalInputTokens: ps.TotalInputTokens,
|
||||
TotalCachedInputTokens: ps.TotalCachedInputTokens,
|
||||
TotalCacheCreationTokens: ps.TotalCacheCreationTokens,
|
||||
TotalOutputTokens: ps.TotalOutputTokens,
|
||||
TotalRequests: ps.TotalRequests,
|
||||
Estimated: ps.Estimated,
|
||||
LastTurnCostUSD: ps.LastTurnCostUSD,
|
||||
SessionCostUSD: ps.SessionCostUSD,
|
||||
}
|
||||
for _, m := range ps.Messages {
|
||||
if m.Role == "user" {
|
||||
s.goal = m.Content
|
||||
break
|
||||
|
|
|
|||
Reference in New Issue