Deliver inbox answers mid-turn through the PostToolUse hook
This commit is contained in:
+69
-10
@@ -304,11 +304,21 @@ func (m *Manager) Deliver(ctx context.Context, sessionID string) error {
|
||||
m.deliverMu.Lock()
|
||||
defer m.deliverMu.Unlock()
|
||||
|
||||
pending, err := m.store.Undelivered(ctx, sessionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(pending) == 0 {
|
||||
return nil
|
||||
}
|
||||
ids := responseIDs(pending)
|
||||
|
||||
sess, err := m.store.GetSession(ctx, sessionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sess.State != api.AgentSessionStateIdle {
|
||||
slog.Info("deliver held: session not idle", "session", sessionID, "state", sess.State, "responses", ids)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -317,14 +327,7 @@ func (m *Manager) Deliver(ctx context.Context, sessionID string) error {
|
||||
return err
|
||||
}
|
||||
if waiting > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pending, err := m.store.Undelivered(ctx, sessionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(pending) == 0 {
|
||||
slog.Info("deliver held: blocking question waiting", "session", sessionID, "waiting", waiting, "responses", ids)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -333,19 +336,75 @@ func (m *Manager) Deliver(ctx context.Context, sessionID string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = m.turn(ctx, sess, task, pending[0].Response.User, deliveryMessage(pending), nil)
|
||||
after, err := m.turn(ctx, sess, task, pending[0].Response.User, deliveryMessage(pending), nil)
|
||||
if errors.Is(err, ErrConflict) {
|
||||
slog.Info("deliver held: session changed state", "session", sessionID, "err", err, "responses", ids)
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
slog.Error("deliver failed", "session", sessionID, "err", err, "responses", ids)
|
||||
return err
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
l := m.live[sessionID]
|
||||
closing := m.closing
|
||||
m.mu.Unlock()
|
||||
pid := 0
|
||||
exited := false
|
||||
if l != nil {
|
||||
pid = l.sess.Pid()
|
||||
exited = l.sess.Exited()
|
||||
}
|
||||
slog.Info("deliver sent", "session", sessionID, "state", after.State, "pid", pid, "exited", exited, "closing", closing, "responses", ids)
|
||||
return m.store.MarkDelivered(ctx, ids)
|
||||
}
|
||||
|
||||
func (m *Manager) deliverMidTurn(ctx context.Context, l *live) string {
|
||||
m.deliverMu.Lock()
|
||||
defer m.deliverMu.Unlock()
|
||||
|
||||
pending, err := m.store.Undelivered(ctx, l.id)
|
||||
if err != nil {
|
||||
slog.Error("list undelivered responses", "session", l.id, "err", err)
|
||||
return ""
|
||||
}
|
||||
if len(pending) == 0 {
|
||||
return ""
|
||||
}
|
||||
ids := responseIDs(pending)
|
||||
|
||||
waiting, err := m.store.AwaitingHuman(ctx, l.id)
|
||||
if err != nil {
|
||||
slog.Error("count blocking questions", "session", l.id, "err", err)
|
||||
return ""
|
||||
}
|
||||
if waiting > 0 {
|
||||
slog.Info("deliver held mid-turn: blocking question waiting", "session", l.id, "waiting", waiting, "responses", ids)
|
||||
return ""
|
||||
}
|
||||
|
||||
err = m.store.MarkDelivered(ctx, ids)
|
||||
if err != nil {
|
||||
slog.Error("mark responses delivered", "session", l.id, "err", err, "responses", ids)
|
||||
return ""
|
||||
}
|
||||
|
||||
text := deliveryMessage(pending)
|
||||
err = m.emit(ctx, l, pending[0].Response.User, "user.message", map[string]any{"text": text, "mid_turn": true})
|
||||
if err != nil {
|
||||
slog.Error("record mid-turn delivery", "session", l.id, "err", err)
|
||||
}
|
||||
slog.Info("deliver sent mid-turn", "session", l.id, "responses", ids)
|
||||
return text
|
||||
}
|
||||
|
||||
func responseIDs(pending []store.Pending) []string {
|
||||
ids := []string{}
|
||||
for _, p := range pending {
|
||||
ids = append(ids, p.Response.Id)
|
||||
}
|
||||
return m.store.MarkDelivered(ctx, ids)
|
||||
return ids
|
||||
}
|
||||
|
||||
func deliveryMessage(pending []store.Pending) string {
|
||||
|
||||
Reference in New Issue
Block a user