toolsrv: per-agent tool registry
Tools are now scoped per-agent within a session. The registry uses OLLIE_UNAME (agent identity) to partition loaded tools. Each agent sees only its own tools — load/unload/list/lookup all key on the agent ID read from the toolsrv environment.
This commit is contained in:
parent
7dfd769c25
commit
659f89fcbf
|
|
@ -117,29 +117,36 @@ func (st *State) GetEnv(key string) string {
|
|||
|
||||
// --- Tool Registry ---
|
||||
|
||||
// ListTools returns loaded tools.
|
||||
// agentID returns the current agent identity from the environment.
|
||||
func (st *State) agentID() string {
|
||||
return st.env["OLLIE_UNAME"]
|
||||
}
|
||||
|
||||
// ListTools returns loaded tools for the current agent.
|
||||
func (st *State) ListTools() []toolsrv.ToolInfo {
|
||||
st.mu.RLock()
|
||||
reg := st.registry
|
||||
aid := st.agentID()
|
||||
st.mu.RUnlock()
|
||||
|
||||
if reg == nil {
|
||||
return nil
|
||||
}
|
||||
return reg.Loaded()
|
||||
return reg.Loaded(aid)
|
||||
}
|
||||
|
||||
// LoadTool loads a tool by name into the registry.
|
||||
// LoadTool loads a tool by name for the current agent.
|
||||
func (st *State) LoadTool(name string) error {
|
||||
st.mu.RLock()
|
||||
reg := st.registry
|
||||
aid := st.agentID()
|
||||
st.mu.RUnlock()
|
||||
|
||||
if reg == nil {
|
||||
return fmt.Errorf("no tool registry configured")
|
||||
}
|
||||
|
||||
if err := reg.Load(name); err != nil {
|
||||
if err := reg.Load(aid, name); err != nil {
|
||||
return err
|
||||
}
|
||||
if st.OnToolsChanged != nil {
|
||||
|
|
@ -148,17 +155,18 @@ func (st *State) LoadTool(name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// UnloadTool removes a tool from the registry.
|
||||
// UnloadTool removes a tool from the current agent's registry.
|
||||
func (st *State) UnloadTool(name string) error {
|
||||
st.mu.RLock()
|
||||
reg := st.registry
|
||||
aid := st.agentID()
|
||||
st.mu.RUnlock()
|
||||
|
||||
if reg == nil {
|
||||
return fmt.Errorf("no tool registry configured")
|
||||
}
|
||||
|
||||
if err := reg.Unload(name); err != nil {
|
||||
if err := reg.Unload(aid, name); err != nil {
|
||||
return err
|
||||
}
|
||||
if st.OnToolsChanged != nil {
|
||||
|
|
@ -200,6 +208,7 @@ func (st *State) NewProc(ctx context.Context, payload string, background bool) (
|
|||
// Look up tool
|
||||
st.mu.RLock()
|
||||
reg := st.registry
|
||||
aid := st.agentID()
|
||||
cwd := st.cwd
|
||||
yolo := st.yolo
|
||||
envCopy := make(map[string]string)
|
||||
|
|
@ -212,7 +221,7 @@ func (st *State) NewProc(ctx context.Context, payload string, background bool) (
|
|||
return "", 0, fmt.Errorf("tool registry not configured")
|
||||
}
|
||||
|
||||
info, ok := reg.Lookup(toolName)
|
||||
info, ok := reg.Lookup(aid, toolName)
|
||||
if !ok {
|
||||
return "", 0, fmt.Errorf("tool not found: %s", toolName)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Package registry provides the tool registry for toolsrv.
|
||||
// One toolsrv per session, so no session-scoping needed.
|
||||
// Tools are scoped per-agent within a session (one toolsrv per session).
|
||||
package registry
|
||||
|
||||
import (
|
||||
|
|
@ -10,17 +10,18 @@ import (
|
|||
"ollie/toolsrv"
|
||||
)
|
||||
|
||||
// Registry tracks loaded tools.
|
||||
// Registry tracks loaded tools per agent.
|
||||
type Registry struct {
|
||||
mu sync.RWMutex
|
||||
tools map[string]toolsrv.ToolInfo
|
||||
revision uint64
|
||||
mu sync.RWMutex
|
||||
agents map[string]map[string]toolsrv.ToolInfo
|
||||
revisions map[string]uint64
|
||||
}
|
||||
|
||||
// New creates a new tool registry.
|
||||
func New() (*Registry, error) {
|
||||
return &Registry{
|
||||
tools: make(map[string]toolsrv.ToolInfo),
|
||||
agents: make(map[string]map[string]toolsrv.ToolInfo),
|
||||
revisions: make(map[string]uint64),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -34,8 +35,8 @@ func (r *Registry) discover() map[string]toolsrv.ToolInfo {
|
|||
return tools
|
||||
}
|
||||
|
||||
// Load loads a tool into the registry.
|
||||
func (r *Registry) Load(name string) error {
|
||||
// Load loads a tool for the given agent.
|
||||
func (r *Registry) Load(agentID, name string) error {
|
||||
tools := r.discover()
|
||||
tool, exists := tools[name]
|
||||
if !exists {
|
||||
|
|
@ -45,50 +46,69 @@ func (r *Registry) Load(name string) error {
|
|||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
r.tools[name] = tool
|
||||
r.revision++
|
||||
if r.agents[agentID] == nil {
|
||||
r.agents[agentID] = make(map[string]toolsrv.ToolInfo)
|
||||
}
|
||||
|
||||
r.agents[agentID][name] = tool
|
||||
r.revisions[agentID]++
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unload removes a tool from the registry.
|
||||
func (r *Registry) Unload(name string) error {
|
||||
// Unload removes a tool from an agent's registry.
|
||||
func (r *Registry) Unload(agentID, name string) error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
if _, exists := r.tools[name]; !exists {
|
||||
agentTools, ok := r.agents[agentID]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
delete(r.tools, name)
|
||||
r.revision++
|
||||
if _, exists := agentTools[name]; !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
delete(agentTools, name)
|
||||
r.revisions[agentID]++
|
||||
return nil
|
||||
}
|
||||
|
||||
// Loaded returns all loaded tools.
|
||||
func (r *Registry) Loaded() []toolsrv.ToolInfo {
|
||||
// Loaded returns all loaded tools for an agent.
|
||||
func (r *Registry) Loaded(agentID string) []toolsrv.ToolInfo {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
agentTools, ok := r.agents[agentID]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var loaded []toolsrv.ToolInfo
|
||||
for _, info := range r.tools {
|
||||
for _, info := range agentTools {
|
||||
loaded = append(loaded, info)
|
||||
}
|
||||
sort.Slice(loaded, func(i, j int) bool { return loaded[i].Name < loaded[j].Name })
|
||||
return loaded
|
||||
}
|
||||
|
||||
// Lookup returns a tool by name.
|
||||
func (r *Registry) Lookup(name string) (toolsrv.ToolInfo, bool) {
|
||||
// Lookup returns a tool by name for an agent.
|
||||
func (r *Registry) Lookup(agentID, name string) (toolsrv.ToolInfo, bool) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
tool, exists := r.tools[name]
|
||||
agentTools, ok := r.agents[agentID]
|
||||
if !ok {
|
||||
return toolsrv.ToolInfo{}, false
|
||||
}
|
||||
|
||||
tool, exists := agentTools[name]
|
||||
return tool, exists
|
||||
}
|
||||
|
||||
// Revision returns the registry revision counter.
|
||||
func (r *Registry) Revision() uint64 {
|
||||
// Revision returns the revision counter for an agent's tools.
|
||||
func (r *Registry) Revision(agentID string) uint64 {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
return r.revision
|
||||
return r.revisions[agentID]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue