Deliver inbox answers mid-turn through the PostToolUse hook
This commit is contained in:
@@ -275,6 +275,7 @@ func (m *Manager) Recover(ctx context.Context) error {
|
||||
l, err := m.ensureLive(ctx, sess, task)
|
||||
if err != nil {
|
||||
slog.Error("resume session", "session", sess.Id, "err", err)
|
||||
m.logUndelivered(ctx, sess.Id, "resume failed")
|
||||
err = m.store.SetSessionState(ctx, sess.Id, api.AgentSessionStateIdle, "byre", map[string]any{"error": err.Error()})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -290,12 +291,33 @@ func (m *Manager) Recover(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
slog.Info("resumed session", "session", sess.Id, "task", task.Id, "owner", sess.Owner)
|
||||
m.logUndelivered(ctx, sess.Id, "resumed with restart notice")
|
||||
}
|
||||
|
||||
idle, err := m.store.SessionsInState(ctx, api.AgentSessionStateIdle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, sess := range idle {
|
||||
m.logUndelivered(ctx, sess.Id, "idle at startup")
|
||||
}
|
||||
|
||||
go m.deliverAllLeads()
|
||||
return m.drain(ctx)
|
||||
}
|
||||
|
||||
func (m *Manager) logUndelivered(ctx context.Context, sessionID, reason string) {
|
||||
pending, err := m.store.Undelivered(ctx, sessionID)
|
||||
if err != nil {
|
||||
slog.Error("list undelivered responses", "session", sessionID, "err", err)
|
||||
return
|
||||
}
|
||||
if len(pending) == 0 {
|
||||
return
|
||||
}
|
||||
slog.Info("undelivered responses", "session", sessionID, "reason", reason, "responses", responseIDs(pending))
|
||||
}
|
||||
|
||||
func (m *Manager) Close() {
|
||||
close(m.watchStop)
|
||||
|
||||
@@ -510,7 +532,17 @@ func (m *Manager) cancelQueued(ctx context.Context, sess api.AgentSession) (api.
|
||||
m.capMu.Lock()
|
||||
defer m.capMu.Unlock()
|
||||
|
||||
err := m.store.DeleteQueuedTurn(ctx, sess.Id)
|
||||
queued, err := m.store.QueuedTurns(ctx)
|
||||
if err != nil {
|
||||
return api.AgentSession{}, err
|
||||
}
|
||||
for _, q := range queued {
|
||||
if q.SessionID == sess.Id && strings.HasPrefix(q.Text, "Responses from your inbox:") {
|
||||
slog.Info("cancelled queued turn carried inbox responses", "session", sess.Id, "text", q.Text)
|
||||
}
|
||||
}
|
||||
|
||||
err = m.store.DeleteQueuedTurn(ctx, sess.Id)
|
||||
if errors.Is(err, store.ErrNotFound) {
|
||||
return api.AgentSession{}, fmt.Errorf("%w: session %s has no queued turn", ErrConflict, sess.Id)
|
||||
}
|
||||
@@ -607,7 +639,7 @@ func (m *Manager) ensureLive(ctx context.Context, sess api.AgentSession, task ap
|
||||
hooks := map[string][]claude.HookMatcher{
|
||||
"UserPromptSubmit": {{Func: remindGuidance(g)}},
|
||||
"Stop": {{Func: m.bounceProseQuestion(l)}},
|
||||
"PostToolUse": {{Func: m.snapshotAfterTool(l)}},
|
||||
"PostToolUse": {{Func: m.afterTool(l)}},
|
||||
}
|
||||
if l.owner != "" {
|
||||
l.dir = filepath.Join(m.leadRoot, url.PathEscape(l.owner))
|
||||
@@ -682,6 +714,7 @@ func (m *Manager) pump(l *live) {
|
||||
m.mu.Unlock()
|
||||
|
||||
if quiet {
|
||||
m.logUndelivered(ctx, l.id, "agent process ended while closing or stopping")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -695,6 +728,7 @@ func (m *Manager) pump(l *live) {
|
||||
return
|
||||
}
|
||||
|
||||
m.logUndelivered(ctx, l.id, "agent process exited mid-turn")
|
||||
err = m.store.SetSessionState(ctx, l.id, api.AgentSessionStateIdle, agentActor, map[string]any{"error": "agent process exited mid-turn"})
|
||||
if err != nil {
|
||||
slog.Error("record session exit", "session", l.id, "err", err)
|
||||
@@ -822,11 +856,13 @@ func (m *Manager) handle(ctx context.Context, l *live, ev claude.Event) error {
|
||||
slog.Error("start queued turns", "err", err)
|
||||
}
|
||||
if handoff {
|
||||
m.logUndelivered(ctx, l.id, "turn ended in handoff")
|
||||
go m.continueFromHandoff(l.id, res.Result)
|
||||
return nil
|
||||
}
|
||||
mergeBy := m.takeMerge(l.taskID)
|
||||
if mergeBy != "" && finished {
|
||||
m.logUndelivered(ctx, l.id, "turn ended in merge")
|
||||
go m.finishMerge(l, mergeBy)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user