Details (original message): Implement the backend: store/bus/runmgr core, mock and LLM runners (agent-native client), HITL three-branch routing, subagent runs, builtin and declarative HTTP tools, ingest parsers (md/txt/docx/pdf-text), knowledge fulltext, layered settings, profiles, plugin host, REST+SSE API, single-binary entrypoint; e2e and unit tests.
53 lines
1.2 KiB
Go
53 lines
1.2 KiB
Go
// Package bus 是 streamhub:按会话分发已持久化的事件(SSE 通道)。
|
|
// 事件权威在 store(seq 游标);bus 只做在线转发,溢出丢弃由客户端从游标重放补偿。
|
|
package bus
|
|
|
|
import (
|
|
"sync"
|
|
|
|
core "agent-system-core"
|
|
)
|
|
|
|
type subscriber struct {
|
|
ch chan core.StreamEvent
|
|
filter string // conversationID;空 = 全部
|
|
}
|
|
|
|
type Bus struct {
|
|
mu sync.Mutex
|
|
subs map[int64]*subscriber
|
|
next int64
|
|
}
|
|
|
|
func New() *Bus { return &Bus{subs: map[int64]*subscriber{}} }
|
|
|
|
// Subscribe 返回新订阅;close(unsubscribe) 注销。
|
|
func (b *Bus) Subscribe(conversationID string) (<-chan core.StreamEvent, func()) {
|
|
b.mu.Lock()
|
|
id := b.next
|
|
b.next++
|
|
ch := make(chan core.StreamEvent, 512)
|
|
b.subs[id] = &subscriber{ch: ch, filter: conversationID}
|
|
b.mu.Unlock()
|
|
return ch, func() {
|
|
b.mu.Lock()
|
|
delete(b.subs, id)
|
|
b.mu.Unlock()
|
|
}
|
|
}
|
|
|
|
// Publish 非阻塞广播;满则丢(客户端 Last-Event-ID 重放补齐)。
|
|
func (b *Bus) Publish(e core.StreamEvent) {
|
|
b.mu.Lock()
|
|
defer b.mu.Unlock()
|
|
for _, s := range b.subs {
|
|
if s.filter != "" && s.filter != e.ConversationID {
|
|
continue
|
|
}
|
|
select {
|
|
case s.ch <- e:
|
|
default:
|
|
}
|
|
}
|
|
}
|