From f8ed2189f12ff14bb8729a5adbfa645e2a402625 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Fri, 17 Jul 2026 22:07:26 +0200 Subject: [PATCH] agent: inject detached process output on exit When a detached process exits, its output (last 2KB of ring buffer) is queued as a prompt wrapped in tags. The agent sees it on its next turn (or immediately if idle via Queue). - InjectSystemEvent(content) added to Core interface - SetOnExit(fn) added to execute.Server for external hook wiring --- pkg/agent/core.go | 4 ++++ pkg/agent/types.go | 5 +++++ pkg/tools/execute/server.go | 3 +++ 3 files changed, 12 insertions(+) diff --git a/pkg/agent/core.go b/pkg/agent/core.go index d76c00f..b855a79 100644 --- a/pkg/agent/core.go +++ b/pkg/agent/core.go @@ -540,6 +540,10 @@ func (s *agent) DismissDetached(pid int) bool { return false } +func (s *agent) InjectSystemEvent(content string) { + s.Queue("\n" + content + "\n") +} + func (s *agent) AgentName() string { v := s.agentName s.log.Debug("AgentName() = %q", v) diff --git a/pkg/agent/types.go b/pkg/agent/types.go index 50feaf2..2192968 100644 --- a/pkg/agent/types.go +++ b/pkg/agent/types.go @@ -162,6 +162,11 @@ type Core interface { // DismissDetached removes an exited process from the list. DismissDetached(pid int) bool + + // InjectSystemEvent appends a system-originated message to the session + // context and emits it on the event bus. The agent sees it on its next + // turn; it appears in the chat log immediately. + InjectSystemEvent(content string) } // DetachedInfo describes a detached process for external consumers. diff --git a/pkg/tools/execute/server.go b/pkg/tools/execute/server.go index 5645197..9d09877 100644 --- a/pkg/tools/execute/server.go +++ b/pkg/tools/execute/server.go @@ -89,6 +89,9 @@ func WithOnPreDispatch(fn func()) Option { return func(s *Server) { s.OnPreDispa // WithOnClose registers a hook called during Close. func WithOnClose(fn func()) Option { return func(s *Server) { s.OnClose = fn } } +// SetOnExit sets the hook called when a detached process exits. +func (e *Server) SetOnExit(fn func(pid, exitCode int)) { e.OnExit = fn } + // WithOnEnvSet registers a hook called each time SetEnv is called. func WithOnEnvSet(fn func(key, value string)) Option { return func(s *Server) { s.OnEnvSet = fn } }