diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index d48220c..cee06e6 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -65,19 +65,31 @@ func run(ctx context.Context, cfg agentConfig, state state) error { // sync.Map is required because execOne may run in concurrent goroutines. var resultCache sync.Map + // stepCtx carries per-turn context assembled once at the top of each iteration. + type StepContext struct { + Goal string + TaskState *TaskState + Recent []backend.Message // last N messages (hot window) + } + for { + sc := StepContext{ + Goal: cfg.preamble, + TaskState: state.taskState(), + Recent: state.recentHistory(hotTailSize), + } + var history []backend.Message - if ts := state.taskState(); ts != nil { - // Structured mode: task state + recent tail only. - history = state.recentHistory(hotTailSize) + if sc.TaskState != nil { + history = sc.Recent } else { history = state.history() } - if cfg.preamble != "" { - history = append([]backend.Message{{Role: "system", Content: cfg.preamble}}, history...) + if sc.Goal != "" { + history = append([]backend.Message{{Role: "system", Content: sc.Goal}}, history...) } - if ts := state.taskState(); ts != nil { - if msg := ts.render(); msg != "" && len(history) > 0 { + if sc.TaskState != nil { + if msg := sc.TaskState.render(); msg != "" && len(history) > 0 { // Insert after system prompt, before conversation. history = append([]backend.Message{history[0], {Role: "user", Content: msg}}, history[1:]...) }