From 8f7d21fc3802c23d2586c6ffdbf7952768f07696 Mon Sep 17 00:00:00 2001 From: Ollie Agent Date: Sat, 8 Aug 2026 14:02:22 +0200 Subject: [PATCH] toolsrv: fire OnToolsChanged after LoadTool The system prompt tool listing now refreshes immediately on tool_load instead of only on file-watcher events. buildToolListing helper added to format the listing in the same format BuildPreamble uses. Also updates kde submodule: GUI auto-switches to newly created agent, removes remote field from agent dialog. --- kde | 2 +- toolsrv/accessors.go | 15 +++++++++++++++ toolsrv/server.go | 11 ++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/kde b/kde index 7039009..e24d332 160000 --- a/kde +++ b/kde @@ -1 +1 @@ -Subproject commit 70390097b01e5a3d7ae6f55d84673bb0dc84fb01 +Subproject commit e24d332d50fdeac0703bf93b39c04513fd158bd7 diff --git a/toolsrv/accessors.go b/toolsrv/accessors.go index b7c818e..3bead9c 100644 --- a/toolsrv/accessors.go +++ b/toolsrv/accessors.go @@ -2,6 +2,8 @@ package toolsrv import ( "context" + "fmt" + "strings" ) // --- Exported accessors for builtin tool handlers --- @@ -40,3 +42,16 @@ func (e *Server) ExecuteInSandbox(ctx context.Context, cmd, language string, tim func (e *Server) ExecuteElevated(ctx context.Context, cmd, dir string, timeout int, detach bool) (string, error) { return e.executeElevated(ctx, cmd, dir, timeout, detach) } + +// buildToolListing formats a slice of ToolInfo into the preamble listing +// format consumed by agent.refreshToolListing: "- **name** — description\n" per entry. +// Only local tools (Server == "") with a non-empty description are included. +func buildToolListing(infos []ToolInfo) string { + var sb strings.Builder + for _, ti := range infos { + if ti.Description != "" && ti.Server == "" { + fmt.Fprintf(&sb, "- **%s** — %s\n", ti.Name, ti.Description) + } + } + return sb.String() +} diff --git a/toolsrv/server.go b/toolsrv/server.go index a68b89a..d407c74 100644 --- a/toolsrv/server.go +++ b/toolsrv/server.go @@ -127,6 +127,8 @@ func WithToolRegistry(r *Registry, sessionID string) Option { // LoadTool loads a tool by name into this server's tool registry. // Returns an error if no registry is configured or the tool cannot be found. +// If OnToolsChanged is set, it is called with the updated tool listing so the +// system prompt reflects the newly available tool immediately. func (e *Server) LoadTool(name string) error { if e.toolRegistry == nil { return fmt.Errorf("no tool registry configured") @@ -134,7 +136,14 @@ func (e *Server) LoadTool(name string) error { if e.sessionID == "" { return fmt.Errorf("no session ID configured") } - return e.toolRegistry.Load(e.sessionID, name) + if err := e.toolRegistry.Load(e.sessionID, name); err != nil { + return err + } + if e.OnToolsChanged != nil { + listing := buildToolListing(e.toolRegistry.Loaded(e.sessionID)) + e.OnToolsChanged(listing) + } + return nil }