agent: add chat log fields and methods
Moved log buffer, plan, mutex, and condvar onto agent.Agent directly. These were previously on the fs package's AgentLog type. The fs package will be migrated to use these in the next commit. New methods: AppendChat, EnsureTrailingNewline, ChatMu, ChatCond, ChatLog, Plan, SetPlan.
This commit is contained in:
parent
b01dbdfba8
commit
31d3466b3b
|
|
@ -56,6 +56,13 @@ type Agent struct {
|
|||
save func() // trigger debounced persistence
|
||||
flush func() // immediately flush persistence
|
||||
onStateChange func(agentID, state string) // optional callback for state changes
|
||||
|
||||
// Chat log — the rendered output stream, exposed via 9P.
|
||||
chatMu sync.RWMutex
|
||||
chatLog []byte
|
||||
chatVers uint32
|
||||
chatCond *sync.Cond
|
||||
plan []byte
|
||||
}
|
||||
|
||||
// Backend returns the active backend from the runtime.
|
||||
|
|
@ -116,6 +123,56 @@ func (ag *Agent) SetName(name string) {
|
|||
// ID returns the agent's unique identity.
|
||||
func (ag *Agent) ID() string { return ag.id }
|
||||
|
||||
// --- Chat log methods ---
|
||||
|
||||
// AppendChat appends data to the chat log and notifies stream readers.
|
||||
func (ag *Agent) AppendChat(data []byte) {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
}
|
||||
ag.chatMu.Lock()
|
||||
ag.chatLog = append(ag.chatLog, data...)
|
||||
ag.chatVers++
|
||||
ag.chatMu.Unlock()
|
||||
ag.chatCond.Broadcast()
|
||||
}
|
||||
|
||||
// EnsureTrailingNewline appends a newline if the log doesn't end with one.
|
||||
func (ag *Agent) EnsureTrailingNewline() {
|
||||
ag.chatMu.Lock()
|
||||
if len(ag.chatLog) > 0 && ag.chatLog[len(ag.chatLog)-1] != '\n' {
|
||||
ag.chatLog = append(ag.chatLog, '\n')
|
||||
}
|
||||
ag.chatVers++
|
||||
ag.chatMu.Unlock()
|
||||
}
|
||||
|
||||
// ChatMu returns the chat log mutex for external locking (streaming).
|
||||
func (ag *Agent) ChatMu() *sync.RWMutex { return &ag.chatMu }
|
||||
|
||||
// ChatCond returns the condvar for blocking chat readers.
|
||||
func (ag *Agent) ChatCond() *sync.Cond { return ag.chatCond }
|
||||
|
||||
// ChatLog returns the raw chat log bytes (caller must hold ChatMu.RLock).
|
||||
func (ag *Agent) ChatLog() []byte { return ag.chatLog }
|
||||
|
||||
// Plan returns a copy of the plan.
|
||||
func (ag *Agent) Plan() []byte {
|
||||
ag.chatMu.RLock()
|
||||
p := make([]byte, len(ag.plan))
|
||||
copy(p, ag.plan)
|
||||
ag.chatMu.RUnlock()
|
||||
return p
|
||||
}
|
||||
|
||||
// SetPlan replaces the plan.
|
||||
func (ag *Agent) SetPlan(data []byte) {
|
||||
ag.chatMu.Lock()
|
||||
ag.plan = make([]byte, len(data))
|
||||
copy(ag.plan, data)
|
||||
ag.chatMu.Unlock()
|
||||
}
|
||||
|
||||
// BackendName returns the name of the active backend.
|
||||
func (ag *Agent) BackendName() string {
|
||||
if ag.runtime.Backend == nil {
|
||||
|
|
@ -651,6 +708,7 @@ func NewAgent(cfg AgentParams) *Agent {
|
|||
state: "idle",
|
||||
}
|
||||
ag.signalCh = make(chan struct{})
|
||||
ag.chatCond = sync.NewCond(ag.chatMu.RLocker())
|
||||
ag.SetSessionEnv(cfg.SessionID)
|
||||
return ag
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue