Add a pause that holds an agent after its current step

This commit is contained in:
Ian Gulliver
2026-10-22 21:55:42 -07:00
parent 73519bf4dd
commit 293c21ca8c
25 changed files with 1014 additions and 472 deletions
@@ -0,0 +1 @@
ALTER TABLE agent_sessions ADD COLUMN paused INTEGER NOT NULL DEFAULT 0;
+28 -2
View File
@@ -1376,6 +1376,32 @@ func (s *Store) SessionsWithSubagents(ctx context.Context) ([]api.AgentSession,
return s.querySessions(ctx, `SELECT `+sessionColumns+` FROM agent_sessions WHERE subagents > 0`)
}
func (s *Store) PausedSessions(ctx context.Context) ([]api.AgentSession, error) {
return s.querySessions(ctx, `SELECT `+sessionColumns+` FROM agent_sessions WHERE paused AND state != ?`, string(api.AgentSessionStateCompleted))
}
func (s *Store) SetSessionPaused(ctx context.Context, id string, paused bool, actor string) error {
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
taskID := ""
projectID := ""
owner := ""
err := tx.QueryRowContext(ctx, `
SELECT coalesce(t.id, ''), coalesce(t.project_id, ''), s.owner FROM agent_sessions s LEFT JOIN tasks t ON t.id = s.task_id WHERE s.id = ?
`, id).Scan(&taskID, &projectID, &owner)
if errors.Is(err, sql.ErrNoRows) {
return ErrNotFound
}
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, `UPDATE agent_sessions SET paused = ? WHERE id = ?`, paused, id)
if err != nil {
return err
}
return emit(sessionEvent("session.paused", projectID, taskID, owner, id, actor, map[string]any{"paused": paused}))
})
}
func (s *Store) SetSubagents(ctx context.Context, id string, n int, actor string) error {
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
taskID := ""
@@ -1701,7 +1727,7 @@ const backgroundExpr = `(audit != '' OR EXISTS (SELECT 1 FROM tasks r WHERE r.id
AND (kind != 'task.discard_suggested'
OR (kind = 'task.discard_suggested' AND NOT EXISTS (SELECT 1 FROM tasks r JOIN workflow_definitions d ON d.id = r.workflow_definition_id WHERE r.id IN (tasks.id, tasks.parent_task_id) AND d.auto_discard))))`
const sessionColumns = `id, coalesce(task_id, ''), owner, vendor, model, vendor_session_id, state, role, member, created_by, created_at, forked_from, forked_at, subagents`
const sessionColumns = `id, coalesce(task_id, ''), owner, vendor, model, vendor_session_id, state, role, member, created_by, created_at, forked_from, forked_at, subagents, paused`
type scanner interface {
Scan(dest ...any) error
@@ -1809,7 +1835,7 @@ func scanSession(row scanner) (api.AgentSession, error) {
createdAt := ""
forkedFrom := ""
forkedAt := ""
err := row.Scan(&sess.Id, &sess.TaskId, &sess.Owner, &vendor, &sess.Model, &sess.VendorSessionId, &state, &role, &sess.Member, &sess.CreatedBy, &createdAt, &forkedFrom, &forkedAt, &sess.Subagents)
err := row.Scan(&sess.Id, &sess.TaskId, &sess.Owner, &vendor, &sess.Model, &sess.VendorSessionId, &state, &role, &sess.Member, &sess.CreatedBy, &createdAt, &forkedFrom, &forkedAt, &sess.Subagents, &sess.Paused)
if err != nil {
return sess, err
}