X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/56d959f2d573eef1be5c04d0bf1659fa30d36e7c..a6a82d96b4906e9e1f09f45f69f48124f11ae1bb:/turn.go?ds=sidebyside diff --git a/turn.go b/turn.go index d6a1c41..c6ab5e9 100644 --- a/turn.go +++ b/turn.go @@ -9,10 +9,10 @@ import ( "time" ) -// newTurnLoop returns the loop of agent with its memory and its subagents. Its -// calls go through client, and notify gets each event. The clock gives the date -// of a turn. -func newTurnLoop(agent *Agent, memory *Memory, subagents *Subagents, client ChainClient, clock func() time.Time, notify func(Event)) (*TurnLoop, error) { +// newTurnLoop returns the loop of agent with its memory, its subagents, and the +// WhatsApp link of its tools. Its calls go through client, and notify gets each +// event. The clock gives the date of a turn. +func newTurnLoop(agent *Agent, memory *Memory, subagents *Subagents, whatsapp *WhatsApp, client ChainClient, clock func() time.Time, notify func(Event)) (*TurnLoop, error) { layout, err := loadViewLayout(filepath.Join(agent.dir, viewLayoutFileName)) if err != nil { return nil, err @@ -47,6 +47,7 @@ func newTurnLoop(agent *Agent, memory *Memory, subagents *Subagents, client Chai chat: memory, subagents: subagents, runs: l.runs, + whatsapp: whatsapp, workdir: agent.config.Workdir, } @@ -122,18 +123,19 @@ func (l *TurnLoop) Submit(source, text string) (Message, error) { // Submit does. A failed write stops the loop, because the log refuses all // writes after it. func (l *TurnLoop) Report(name, text, status string) { - _, err := l.Work(name, text, status, status != subagentStopped) - if err != nil { + message, err := l.Work(name, text, status) + switch { + case err != nil: l.fail(fmt.Errorf("%w: %w", errChainLogWrite, err)) + case status != subagentStopped: + l.Wake(message) } } // Work logs text as a work message of source, such as the name of a subagent, -// and tells the clients, with status. With wake, the message joins the waiting -// messages and wakes the loop, as a user message of Submit does: it joins the -// first request of a new turn, or the next request of a running turn after the -// tool results. -func (l *TurnLoop) Work(source, text, status string, wake bool) (Message, error) { +// and tells the clients, with status. The message starts no turn until it goes +// to Wake. +func (l *TurnLoop) Work(source, text, status string) (Message, error) { message, err := l.memory.Append("work", text) if err != nil { return Message{}, err @@ -147,20 +149,25 @@ func (l *TurnLoop) Work(source, text, status string, wake bool) (Message, error) Status: status, }) - if !wake { - return message, nil + return message, nil +} + +// Wake adds the logged messages to the waiting messages and wakes the loop +// once, as a user message of Submit does. They join the first request of a new +// turn together, or the next request of a running turn after the tool results. +func (l *TurnLoop) Wake(messages ...Message) { + if len(messages) == 0 { + return } l.mutex.Lock() - l.pending = append(l.pending, message) + l.pending = append(l.pending, messages...) l.mutex.Unlock() select { case l.wake <- struct{}{}: default: } - - return message, nil } // StopSubagent ends the run of the subagent name and tells if it ran. Its