diff --git a/main.go b/main.go index 067e8d1..78ad464 100644 --- a/main.go +++ b/main.go @@ -179,6 +179,35 @@ func (m *SessionManager) CreateSession(cwd, backendName, modelName, agentName st }) rt := agent.BuildRuntime(cfg, newDisp(), cwd, []string{"OLLIE_SESSION_ID=" + sessID}) + // Wire OnExit hook so detached process exits get injected into agent context. + // We use a pointer indirection because core hasn't been created yet. + var coreRef agent.Core + if srv, ok := rt.Dispatcher.GetServer("execute"); ok { + type exitHooker interface { + SetOnExit(func(int, int)) + } + if eh, ok := srv.(exitHooker); ok { + eh.SetOnExit(func(pid, exitCode int) { + if coreRef == nil { + return + } + var output string + type outputGetter interface { + GetDetachedOutput(int) (string, error) + } + if og, ok := srv.(outputGetter); ok { + output, _ = og.GetDetachedOutput(pid) + } + if len(output) > 2048 { + output = "[...truncated...]\n" + output[len(output)-2048:] + } + msg := fmt.Sprintf("pid %d exited with code %d\n%s", pid, exitCode, output) + coreRef.InjectSystemEvent(msg) + m.conn.Emit(busPath, busIface+".ProcessExited", sessID, int32(pid), int32(exitCode)) + }) + } + } + // Create the agent core core := agent.NewAgentCore(agent.AgentCoreConfig{ Backend: be, @@ -190,6 +219,7 @@ func (m *SessionManager) CreateSession(cwd, backendName, modelName, agentName st Runtime: rt, NewDispatcher: newDisp, }) + coreRef = core ctx, cancel := context.WithCancel(context.Background()) sess := &managedSession{