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
+11 -28
View File
@@ -21,14 +21,13 @@ import (
"time"
"g.fc.run/ai/byre/internal/agentinput"
"g.fc.run/ai/byre/internal/hookcmd"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/procgroup"
)
const maxRuleBytes = 24000
type HookFunc func(ctx context.Context, input json.RawMessage) (map[string]any, error)
type Options struct {
Dir string
Cwd string
@@ -40,7 +39,7 @@ type Options struct {
Reminder string
MCPServers []*mcp.Server
StdioMCP []mcp.Stdio
Hooks map[string]HookFunc
Hooks map[string]hookcmd.Func
OnBadLine func(line []byte, reason string)
}
@@ -167,7 +166,7 @@ func Start(ctx context.Context, opts Options) (*Session, error) {
mux := http.NewServeMux()
mux.HandleFunc("POST /"+token+"/mcp/{server}", s.serveMCP)
mux.HandleFunc("POST /"+token+"/hook/{event}", s.serveHook)
mux.HandleFunc("POST /"+token+"/hook/{event}", hookcmd.Handler(opts.Hooks))
s.srv = &http.Server{Handler: mux}
go s.srv.Serve(ln)
@@ -217,11 +216,16 @@ func (s *Session) writePlugin() error {
hooks := map[string]any{}
for event := range s.opts.Hooks {
hooks[event] = []map[string]any{{
handlers := []map[string]any{{
"type": "command",
"command": fmt.Sprintf("curl -sS --max-time 25 --data-binary @- %s/hook/%s", s.base, event),
"timeout": 30,
"command": hookcmd.Command(s.base + "/hook/" + event),
"timeout": hookcmd.Timeout,
}}
if event == "PreToolUse" || event == "PostToolUse" {
hooks[event] = []map[string]any{{"matcher": "*", "hooks": handlers}}
continue
}
hooks[event] = handlers
}
files := map[string]any{
@@ -282,27 +286,6 @@ func (s *Session) serveMCP(w http.ResponseWriter, r *http.Request) {
w.Write(resp)
}
func (s *Session) serveHook(w http.ResponseWriter, r *http.Request) {
event := r.PathValue("event")
fn := s.opts.Hooks[event]
if fn == nil {
http.NotFound(w, r)
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
out, err := fn(r.Context(), body)
if err != nil {
slog.Error("agy hook failed", "event", event, "err", err)
out = map[string]any{}
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(out)
}
func (s *Session) spawnLocked() error {
args := []string{
"--input-format", "stream-json",