+// newTestTurnLoopWith returns a running loop on a new agent whose builds use
+// summarizer and whose commands run in a temporary directory.
+func newTestTurnLoopWith(t *testing.T, server *ModelFake, summarizer Summarizer) *TurnTestLoop {
+ t.Helper()
+
+ agent, err := openAgent(filepath.Join(t.TempDir(), "agent"))
+ require.NoError(t, err)
+
+ agent.config.Workdir = t.TempDir()
+ clock := newTestClock()
+ memory, err := openMemory(t.Context(), t.TempDir(), clock.Now, summarizer, discardLog())
+ require.NoError(t, err)
+
+ test := &TurnTestLoop{
+ agent: agent,
+ memory: memory,
+ events: &TurnEventRecorder{},
+ logs: &SyncBuffer{},
+ usagePath: filepath.Join(t.TempDir(), "usage.jsonl"),
+ }
+
+ client := newModelClient(server.URL, ModelAPIKey(modelTestKey), agent.CacheKey(), test.usagePath)
+ whatsapp, _, _ := whatsappStartTest(t, t.TempDir(), clock)
+ test.loop, err = newTurnLoop(agent, memory, newTestSubagents(t), whatsapp, newTestSchedules(t, clock.Now), client, clock.Now, daemonTestLogger(test.logs), test.events.Add)
+ require.NoError(t, err)
+
+ ctx, cancel := context.WithCancel(t.Context())
+ done := make(chan error)
+ go func() {
+ done <- test.loop.Run(ctx)
+ }()
+
+ t.Cleanup(func() {
+ cancel()
+ require.ErrorIs(t, <-done, context.Canceled)
+ require.NoError(t, memory.Close())
+ })
+
+ return test
+}
+
+func modelReasoningItem(id, encrypted string) map[string]any {