This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-9p/session/format.go

95 lines
2.5 KiB
Go

package session
import (
agent "ollie/session"
"ollie/backend"
"os"
"strings"
)
func LoadAgentConfig(agentsDir, name string, open func(string) (*os.File, error)) *agent.AgentConfig {
if open == nil {
open = os.Open
}
path := agent.AgentConfigPath(agentsDir, name)
f, err := open(path)
if err != nil {
return nil
}
defer f.Close()
cfg, _ := agent.Load(f)
return cfg
}
// FormatEvent converts an agent Event to bytes for appending to a chat log.
// Streaming roles (assistant, reasoning) return only the content chunk;
// the caller (startEventLog) is responsible for writing the [role] header.
func FormatEvent(ev agent.Event) []byte {
switch ev.Role {
case "user":
return []byte("[user]\n" + ev.Content + "\n")
case "assistant":
return []byte(ev.Content)
case "reasoning":
return []byte(ev.Content)
case "call":
args := squashWhitespace(ev.Content)
return []byte("[call:" + ev.Name + "]\n" + args + "\n")
case "tool":
return []byte("[tool:" + ev.Name + "]\n" + strings.TrimRight(ev.Content, "\n") + "\n")
case "error":
return []byte("[error]\n" + ev.Content + "\n")
case "info":
return []byte("[info]\n" + ev.Content)
case "retry":
return []byte("[retry]\n" + ev.Content + "s\n")
case "stalled":
return []byte("[stalled]\n")
case "maxsteps":
return []byte("[maxsteps]\n" + ev.Content + "\n")
default:
return nil
}
}
func squashWhitespace(s string) string {
return strings.Join(strings.Fields(s), " ")
}
// replayMessagesToLog renders the tail of a persisted message list into the
// session's chat log so that restored sessions show recent history.
func replayMessagesToLog(sess *Session, messages []backend.Message) {
const maxReplay = 20
start := len(messages) - maxReplay
if start < 0 {
start = 0
}
// Skip system messages at the start of the replay window.
for start < len(messages) && messages[start].Role == "system" {
start++
}
for _, m := range messages[start:] {
switch m.Role {
case "system":
// skip
case "user":
sess.AppendLog([]byte("[user]\n" + m.Content + "\n"))
case "assistant":
header := "[assistant]"
if m.ID != "" {
header = "[assistant:" + m.ID + "]"
}
sess.AppendLog([]byte(header + "\n"))
if m.Content != "" {
sess.AppendLog([]byte(m.Content + "\n"))
}
for _, tc := range m.ToolCalls {
args := squashWhitespace(string(tc.Arguments))
sess.AppendLog([]byte("[call:" + tc.Name + "]\n" + args + "\n"))
}
case "tool":
sess.AppendLog([]byte("[tool]\n" + strings.TrimRight(m.Content, "\n") + "\n"))
}
}
}