+// Event tells the clients what the agent does as it happens. Kind is the kind
+// of a logged message (user, reply, tool, echo, note, work), or one of ready,
+// busy, idle, error, and subagent, which tells that the subagent Text starts a
+// run. ID is the ID of a logged message. Source names the client that sent a
+// user message, such as terminal or telegram, so that each client can show the
+// messages of the others, or the subagent of a report. Status tells how the run
+// of a report ended: finished, stopped, or failed.
+type Event struct {
+ Kind string `json:"kind"`
+ ID int `json:"id,omitempty"`
+ Text string `json:"text,omitempty"`
+ Source string `json:"source,omitempty"`
+ Status string `json:"status,omitempty"`
+}
+
+// TurnLoop runs the turns of one agent. A user message goes to the log when it
+// comes, and it wakes the loop. A turn waits until every message before it is
+// summarized. Then the turn runs a Chain whose first request holds the prompt,
+// the tools, and the input of turnInput.
+//
+// The view goes out as the messages of a ViewLayout, so the first request of a
+// turn reads the view of the turn before from the prompt cache. User messages
+// that come during a turn join the next request of its chain after the tool
+// results, and so do the reports of the subagents. The subagents run until the
+// loop ends. Parent and child messages stay queued until the turn finishes.
+// active belongs to the running turn. The mutex protects pending, cancel, and
+// failure.
+type TurnLoop struct {
+ agent *Agent
+ memory *Memory
+ client ChainClient
+ tools *Toolbox
+ runs *SubagentRuns
+ layout *ViewLayout
+ clock func() time.Time
+ logger *slog.Logger
+ notify func(Event)
+ wake chan struct{}
+ messages *DaemonMessages
+ openChild func(context.Context, *Agent) (*DaemonAgent, error)
+ active []Message
+
+ mutex sync.Mutex
+ pending []Message
+ cancel context.CancelFunc
+ failure error
+}
+
+// newTurnLoop returns the loop of agent with its memory, its subagents, and the
+// WhatsApp link and the schedules of its tools. Its calls go through client,
+// and notify gets each event. The clock gives the date of a turn. logger gets
+// the failed turns and the ends of the subagents. A child has no WhatsApp
+// tools, even when the caller supplies a link.
+func newTurnLoop(agent *Agent, memory *Memory, subagents *Subagents, whatsapp *WhatsApp, schedules *Schedules, client ChainClient, clock func() time.Time, logger *slog.Logger, notify func(Event)) (*TurnLoop, error) {