event: emit clear event when agent is cleared

- Add onClear callback to Agent, wired via support.go
- Publish session.{sid}.agent.{aid}.clear event
- GUI listens for agentCleared signal and refreshes chat view
- Works for both GUI clear button and CLI /clear command
This commit is contained in:
Levi Neely 2026-10-09 16:31:30 +02:00
parent 1c863ce9ec
commit 582f7d1b91
6 changed files with 24 additions and 4 deletions

View File

@ -66,6 +66,7 @@ type Agent struct {
flush func() // immediately flush persistence
onStateChange func(agentID, state string) // optional callback for state changes
onProcStart func(agentID string, pid int, tool, cmd string) // optional callback for proc start
onClear func(agentID string) // optional callback for clear
// Chat log — the rendered output stream, exposed via 9P.
chatMu sync.RWMutex
@ -318,6 +319,9 @@ func (ag *Agent) Clear() error {
ag.blockCounter = 0
ag.chatMu.Unlock()
ag.chatCond.Broadcast()
if ag.onClear != nil {
ag.onClear(ag.id)
}
return nil
}

View File

@ -87,6 +87,11 @@ func (ag *Agent) SetOnProcStart(fn func(agentID string, pid int, tool, cmd strin
ag.onProcStart = fn
}
// SetOnClear sets a callback invoked when the agent is cleared.
func (ag *Agent) SetOnClear(fn func(agentID string)) {
ag.onClear = fn
}
// setReply sets the agent's last response.
func (ag *Agent) setReply(reply string) {
ag.stateMu.Lock()

View File

@ -26,6 +26,10 @@ func wireAgentEvents(sessID string, ag *agent.Agent) {
payload := fmt.Sprintf("%d\t%s\t%s", pid, tool, cmd)
session.PublishEvent(topic, payload)
})
ag.SetOnClear(func(agentID string) {
topic := "session." + sessID + ".agent." + agentID + ".clear"
session.PublishEvent(topic, "")
})
}
// ctlCmd is one control verb: its name, a one-line description for the

View File

@ -386,10 +386,7 @@ Item {
font.pixelSize: theme.fontSize > 0 ? theme.fontSize * 0.9 : 11
implicitHeight: 28
enabled: ollie.activeState === "idle"
onClicked: {
ollie.submit("/clear")
chatPane.loadChat() // Refresh the view
}
onClicked: ollie.submit("/clear")
ToolTip.visible: hovered
ToolTip.text: "Clear history and start fresh"
}
@ -676,6 +673,12 @@ Connections {
chatPane.updateCurrentBypass()
}
}
function onAgentCleared(sessionId, agentId) {
// Refresh chat if the cleared agent is the active one
if (sessionId === ollie.activeSessionId && agentId === ollie.activeAgentId) {
chatPane.loadChat()
}
}
// Public functions for keyboard shortcuts
function approveBypass() {

View File

@ -282,6 +282,9 @@ void Ollie9pClient::handleEvent(const QString &eventLine)
}
emit bypassResolved(sidStr, aidStr, id);
}
} else if (agentAction == QLatin1String("clear")) {
// Agent was cleared — emit signal so GUI can refresh chat view
emit agentCleared(sessionId.toString(), agentId.toString());
}
} else {
// Session-level event

View File

@ -123,6 +123,7 @@ signals:
void chatReceived(const QString &text);
void bypassRequested(const QString &sessionId, const QString &agentId, const QString &id, const QString &cmd, const QString &cwd);
void bypassResolved(const QString &sessionId, const QString &agentId, const QString &requestId);
void agentCleared(const QString &sessionId, const QString &agentId);
void pendingBypassCountChanged(const QString &sessionId, const QString &agentId);
void procStarted(const QString &sessionId, const QString &agentId, const QString &payload);
void rootBackendsLoadedChanged();