streaming: tool as first-class streaming role in chat log

This commit is contained in:
Levi Neely 2026-07-19 21:25:58 +02:00
parent bba14ddcde
commit 4b24b33377
1 changed files with 36 additions and 3 deletions

View File

@ -127,7 +127,8 @@ func (sess *Session) EnsureTrailingNewline() {
// startEventLog subscribes to the agent's "event" bus topic and writes
// all events to the session chat log.
func (sess *Session) startEventLog() {
streamingRole := "" // tracks current streaming role ("assistant" or "reasoning")
streamingRole := "" // tracks current streaming role ("assistant", "reasoning", or "tool")
sess.Core.Bus().Subscribe("event", func(ev agent.Event) {
switch ev.Role {
case "assistant", "reasoning":
@ -144,6 +145,40 @@ func (sess *Session) startEventLog() {
streamingRole = ev.Role
}
sess.AppendLog(FormatEvent(ev))
case "tool":
// Tool events can stream (multiple chunks with same name) or
// arrive as a single final result. Write header on first chunk,
// then append content. Duplicate final result is suppressed.
if streamingRole == "tool" {
// Continuation of streaming tool output.
if ev.Content != "" {
sess.AppendLog([]byte(ev.Content))
} else {
// Empty content = final result marker; streaming is done.
sess.AppendLog([]byte("\n"))
streamingRole = ""
}
return
}
if streamingRole != "" {
sess.AppendLog([]byte("\n"))
streamingRole = ""
}
// First tool event — write header and start streaming.
sess.AppendLog([]byte("[tool:" + ev.Name + "]\n"))
if ev.Content != "" {
sess.AppendLog([]byte(ev.Content))
}
streamingRole = "tool"
case "call":
if streamingRole != "" {
sess.AppendLog([]byte("\n"))
streamingRole = ""
}
sess.AppendLog(FormatEvent(ev))
default:
if streamingRole != "" {
sess.AppendLog([]byte("\n"))
@ -1190,8 +1225,6 @@ func FormatEvent(ev agent.Event) []byte {
return []byte("[stalled]\n")
case "maxsteps":
return []byte("[maxsteps]\n" + ev.Content + "\n")
case "exec":
return []byte("[exec]\n" + ev.Content + "\n")
default:
return nil
}