From 7eb022faba4973fa3b1559706e00dab60301a1ee Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Fri, 31 Jul 2026 16:45:37 +0200 Subject: [PATCH] remove built-in skill handlers, replace with external tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skill_list and skill_load are now external shell scripts (data/tools/). Removed from builtins: SkillList, SkillLoad, SkillActive. Removed: toolsrv/skills.go, tools/builtin/skill.go, WithSkillsRegistry, SkillsRegistry accessor, ListSkillsTools. ollie-remote no longer initializes a skills registry. The demarcation: built-ins mutate agent internals (tool schema, context injection). Skills are just file reads — no special treatment needed. --- cmd/ollie-remote/main.go | 3 - cmd/ollie-remote/sandbox/default.yaml | 1 + data/scripts/logseq-cli | 9 ++- tools/builtin/builtins.go | 3 - tools/builtin/skill.go | 83 --------------------------- toolsrv/accessors.go | 4 -- toolsrv/server.go | 10 ---- toolsrv/skills.go | 65 --------------------- 8 files changed, 8 insertions(+), 170 deletions(-) create mode 100644 cmd/ollie-remote/sandbox/default.yaml delete mode 100644 tools/builtin/skill.go delete mode 100644 toolsrv/skills.go diff --git a/cmd/ollie-remote/main.go b/cmd/ollie-remote/main.go index b167c3a..ed40b6f 100644 --- a/cmd/ollie-remote/main.go +++ b/cmd/ollie-remote/main.go @@ -29,7 +29,6 @@ import ( "sync" "syscall" - "ollie/skills" "ollie/toolsrv" "ollie/tools/builtin" ) @@ -82,7 +81,6 @@ func main() { // Build the tool server with builtins and registries. toolReg, _ := toolsrv.NewRegistry() - skillsReg := skills.NewRegistry() agentID := fmt.Sprintf("agent-%d", os.Getpid()) var opts []toolsrv.Option @@ -94,7 +92,6 @@ func main() { if toolReg != nil { opts = append(opts, toolsrv.WithToolRegistry(toolReg, agentID)) } - opts = append(opts, toolsrv.WithSkillsRegistry(skillsReg)) server := toolsrv.New(*cwd) for _, o := range opts { o(server) diff --git a/cmd/ollie-remote/sandbox/default.yaml b/cmd/ollie-remote/sandbox/default.yaml new file mode 100644 index 0000000..99ca5ad --- /dev/null +++ b/cmd/ollie-remote/sandbox/default.yaml @@ -0,0 +1 @@ +# Placeholder — real config copied during build (just ollie-remote) diff --git a/data/scripts/logseq-cli b/data/scripts/logseq-cli index a830d0c..7f053bf 100755 --- a/data/scripts/logseq-cli +++ b/data/scripts/logseq-cli @@ -5,13 +5,18 @@ for cmd in mcp-to-command mcp-remote; do command -v "$cmd" >/dev/null 2>&1 || { echo "Error: Missing required command: $cmd" >&2; exit 1; } done +if [ -z "$OLLIE_LOGSEQ_TOKEN" ]; then + echo "Error: OLLIE_LOGSEQ_TOKEN not set" >&2 + exit 1 +fi + LOGSEQ_MCP_URL="${LOGSEQ_MCP_URL:-http://127.0.0.1:12315}" have_timeout= command -v timeout >/dev/null 2>&1 && have_timeout=1 if [ -n "$have_timeout" ]; then - exec timeout 30 mcp-to-command mcp-remote "$LOGSEQ_MCP_URL/mcp" --transport http-first -- "$@" || { + exec timeout 30 mcp-to-command mcp-remote "$LOGSEQ_MCP_URL/mcp" --transport http-first --header "Authorization: Bearer $OLLIE_LOGSEQ_TOKEN" -- "$@" || { if [ $? -eq 124 ]; then echo "Error: timeout exceeded, may want to retry" >&2 exit 124 @@ -21,4 +26,4 @@ if [ -n "$have_timeout" ]; then } fi -exec mcp-to-command mcp-remote "$LOGSEQ_MCP_URL/mcp" --transport http-first -- "$@" +exec mcp-to-command mcp-remote "$LOGSEQ_MCP_URL/mcp" --transport http-first --header "Authorization: Bearer $OLLIE_LOGSEQ_TOKEN" -- "$@" diff --git a/tools/builtin/builtins.go b/tools/builtin/builtins.go index 93c6d41..6794618 100644 --- a/tools/builtin/builtins.go +++ b/tools/builtin/builtins.go @@ -12,8 +12,5 @@ func Builtins() map[string]toolsrv.Handler { "tool_list": ToolList, "tool_load": ToolLoad, "tool_active": ToolActive, - "skill_list": SkillList, - "skill_load": SkillLoad, - "skill_active": SkillActive, } } diff --git a/tools/builtin/skill.go b/tools/builtin/skill.go deleted file mode 100644 index ced332f..0000000 --- a/tools/builtin/skill.go +++ /dev/null @@ -1,83 +0,0 @@ -package builtin - -import ( - "context" - "encoding/json" - "fmt" - "strings" - - "ollie/toolsrv" -) - -// SkillList lists all available skills from the global registry. -func SkillList(ctx context.Context, srv *toolsrv.Server, args json.RawMessage) (string, error) { - reg := srv.SkillsRegistry() - if reg == nil { - return "", fmt.Errorf("skill_list: no skills registry available") - } - summaries := reg.Summaries() - if len(summaries) == 0 { - return "(no skills found)", nil - } - var out strings.Builder - for _, s := range summaries { - out.WriteString(s.Name) - if s.Description != "" { - out.WriteString(" — ") - out.WriteString(s.Description) - } - out.WriteString("\n") - } - return strings.TrimRight(out.String(), "\n"), nil -} - -// SkillLoad loads a skill into the current session. -func SkillLoad(ctx context.Context, srv *toolsrv.Server, args json.RawMessage) (string, error) { - var a struct { - Name string `json:"name"` - } - if err := json.Unmarshal(args, &a); err != nil { - return "", fmt.Errorf("skill_load: bad args: %w", err) - } - if a.Name == "" { - return "", fmt.Errorf("skill_load: name is required") - } - reg := srv.SkillsRegistry() - sid := srv.SessionID() - if reg == nil || sid == "" { - return "", fmt.Errorf("skill_load: no session registry") - } - if err := reg.Load(sid, a.Name); err != nil { - return "", fmt.Errorf("skill_load: %w", err) - } - content, err := reg.SkillContent(a.Name) - if err != nil { - return "", fmt.Errorf("skill_load: %w", err) - } - injectMsg := fmt.Sprintf("[system: loaded skill %s]\n\n%s", a.Name, content) - srv.InjectContent(injectMsg) - return fmt.Sprintf("loaded: %s (%d bytes)", a.Name, len(content)), nil -} - -// SkillActive lists skills currently loaded in this session. -func SkillActive(ctx context.Context, srv *toolsrv.Server, args json.RawMessage) (string, error) { - reg := srv.SkillsRegistry() - sid := srv.SessionID() - if reg == nil || sid == "" { - return "(no skills loaded)", nil - } - loaded := reg.Loaded(sid) - if len(loaded) == 0 { - return "(no skills loaded)", nil - } - var out strings.Builder - for _, s := range loaded { - out.WriteString(s.Name) - if s.Description != "" { - out.WriteString(" — ") - out.WriteString(s.Description) - } - out.WriteString("\n") - } - return strings.TrimRight(out.String(), "\n"), nil -} diff --git a/toolsrv/accessors.go b/toolsrv/accessors.go index b2e0521..b7c818e 100644 --- a/toolsrv/accessors.go +++ b/toolsrv/accessors.go @@ -2,7 +2,6 @@ package toolsrv import ( "context" - "ollie/skills" ) // --- Exported accessors for builtin tool handlers --- @@ -20,9 +19,6 @@ func (e *Server) ToolRegistry() *Registry { return e.toolRegistry } // SessionID returns the session ID associated with this server. func (e *Server) SessionID() string { return e.sessionID } -// SkillsRegistry returns the attached skills registry, or nil. -func (e *Server) SkillsRegistry() *skills.Registry { return e.skillsRegistry } - // InjectContent calls the OnInjection hook if set. func (e *Server) InjectContent(content string) { if e.OnInjection != nil { diff --git a/toolsrv/server.go b/toolsrv/server.go index a648c69..9d32d95 100644 --- a/toolsrv/server.go +++ b/toolsrv/server.go @@ -11,7 +11,6 @@ import ( "ollie/detach" "ollie/paths" - "ollie/skills" ) const ( @@ -62,7 +61,6 @@ type Server struct { builtins map[string]Handler toolRegistry *Registry - skillsRegistry *skills.Registry sessionID string // OnInjection is called when a skill is loaded and its content @@ -145,11 +143,6 @@ func WithToolRegistry(r *Registry, sessionID string) Option { } } -// WithSkillsRegistry attaches a skills registry to the Server. -func WithSkillsRegistry(r *skills.Registry) Option { - return func(s *Server) { s.skillsRegistry = r } -} - // ListTools implements Server, returning shell plus any // tools promoted in the session's tool registry. @@ -228,9 +221,6 @@ Returns tools with descriptions, one per line.`, if e.toolRegistry != nil && e.sessionID != "" { all = append(all, e.toolRegistry.Loaded(e.sessionID)...) } - // Append skill tools if skills registry is available - skillTools := ListSkillsTools(e.skillsRegistry, e.sessionID) - all = append(all, skillTools...) return all, nil } diff --git a/toolsrv/skills.go b/toolsrv/skills.go deleted file mode 100644 index 9da2e71..0000000 --- a/toolsrv/skills.go +++ /dev/null @@ -1,65 +0,0 @@ -package toolsrv - -import ( - "encoding/json" - - "ollie/skills" -) - -// SetSkillsRegistry attaches a skills registry to the execute server. -// The server uses it to serve skill_list, skill_load, and skill_active. -func (e *Server) SetSkillsRegistry(r *skills.Registry) { - e.skillsRegistry = r -} - -// ListSkillsTools returns ToolInfo entries for the skill_* built-ins. -// These are included alongside the standard tool_* tools. -func ListSkillsTools(skillsReg *skills.Registry, sessionID string) []ToolInfo { - if skillsReg == nil { - return nil - } - tools := []ToolInfo{ - { - Name: "skill_list", - Description: `List available skill modules with name and description. - -Usage: {"name": "skillname"} — if name is provided, loads that skill. -Otherwise lists all skills with descriptions.`, - InputSchema: json.RawMessage(`{ - "type": "object", - "properties": {} - }`), - }, - { - Name: "skill_load", - Description: `Load a skill module into the current session's context. - -Usage: {"name": "skillname"} - -The skill content (SKILL.md body) is injected into the agent's context -and persists across turns.`, - InputSchema: json.RawMessage(`{ - "type": "object", - "required": ["name"], - "properties": { - "name": {"type": "string", "description": "Skill name to load."} - } - }`), - }, - { - Name: "skill_active", - Description: `List skills currently loaded in this session. - -Usage: (no arguments) - -Returns loaded skill names, one per line.`, - InputSchema: json.RawMessage(`{ - "type": "object", - "properties": {} - }`), - }, - } - return tools -} - -// dispatchSkillList lists all available skills from the global registry.