diff --git a/cmd/olliesrv/internal/agent/history.go b/cmd/olliesrv/internal/agent/history.go index 0fdbbfb..63c2628 100644 --- a/cmd/olliesrv/internal/agent/history.go +++ b/cmd/olliesrv/internal/agent/history.go @@ -368,35 +368,6 @@ func (s *History) appendUserMessage(content string) { s.messages = append(s.messages, backend.Message{Role: "user", Content: content}) } -// cloneMessages returns a deep copy of the message slice. -func cloneMessages(msgs []backend.Message) []backend.Message { - out := make([]backend.Message, len(msgs)) - for i, m := range msgs { - out[i] = backend.Message{ - ID: m.ID, - Role: m.Role, - Content: m.Content, - Reasoning: m.Reasoning, - ToolCallID: m.ToolCallID, - } - if len(m.ContentBlocks) > 0 { - out[i].ContentBlocks = make([]backend.ContentBlock, len(m.ContentBlocks)) - copy(out[i].ContentBlocks, m.ContentBlocks) - } - if len(m.ToolCalls) > 0 { - out[i].ToolCalls = make([]backend.ToolCall, len(m.ToolCalls)) - for j, tc := range m.ToolCalls { - out[i].ToolCalls[j] = backend.ToolCall{ - ID: tc.ID, - Name: tc.Name, - Arguments: append(json.RawMessage(nil), tc.Arguments...), - } - } - } - } - return out -} - // estimateTokens returns a rough token count (~4 chars per token). func (s *History) estimateTokens() int { chars := 0 diff --git a/cmd/olliesrv/internal/agent/loop.go b/cmd/olliesrv/internal/agent/loop.go index 0a8e2ab..4a35392 100644 --- a/cmd/olliesrv/internal/agent/loop.go +++ b/cmd/olliesrv/internal/agent/loop.go @@ -121,9 +121,6 @@ func (ag *Agent) run(ctx context.Context) error { for { ag.emit(Event{Role: "state", Content: "thinking"}) - if budget := contextBudget(ctx, rt.Backend); budget > 0 && h.estimateTokens() > budget { - h.stripCold(ctx, rt.Backend) - } history := h.history() diff --git a/cmd/olliesrv/internal/agent/turn.go b/cmd/olliesrv/internal/agent/turn.go index 4da4f58..58b3bb5 100644 --- a/cmd/olliesrv/internal/agent/turn.go +++ b/cmd/olliesrv/internal/agent/turn.go @@ -88,9 +88,9 @@ func (ag *Agent) executeTurn(ctx context.Context, input string) string { // Snapshot messages before this turn modifies them. Restored on context // overflow so the retry starts from a clean state. - var snapMessages []backend.Message + var preTurnLen int if ag.history != nil { - snapMessages = cloneMessages(ag.history.messages) + preTurnLen = len(ag.history.messages) } if ag.history == nil { @@ -197,6 +197,11 @@ func (ag *Agent) executeTurn(ctx context.Context, input string) string { ag.history.resetTurnAccumulators() } + // Strip cold-zone tool results (one batched LLM call per turn). + if ag.history != nil { + ag.history.stripCold(ctx, ag.runtime.Backend) + } + // Inject the preamble system message into history before running. if ag.history != nil { ag.history.injectPreamble(ag.runtime.PreambleString()) @@ -221,7 +226,7 @@ func (ag *Agent) executeTurn(ctx context.Context, input string) string { var ctxErr *backend.ContextOverflowError if !overflowRetried && errors.As(err, &ctxErr) && ag.history != nil { overflowRetried = true - ag.history.messages = snapMessages + ag.history.messages = ag.history.messages[:preTurnLen] ag.emit(Event{Role: "info", Content: "context overflow — compacting and retrying...\n"}) ag.SetState("compacting") if _, cerr := ag.runCompact(ctx, "overflow"); cerr != nil {