tools: pipe JSON args to stdin, sort tool/skill lists
- callPromotedTool now pipes raw JSON object to tool stdin instead of unpacking positional args. Tools parse their own input. - Default schema changed from positional array to empty object. - Registry.Discover() skips files without ollie:prompt marker. - Registry.Summaries() and Loaded() return sorted results (both tools and skills registries).
This commit is contained in:
parent
d5c591ad26
commit
75b76b118e
|
|
@ -4,6 +4,7 @@ package skills
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -86,6 +87,7 @@ func (r *Registry) Summaries() []SkillInfo {
|
|||
for _, info := range r.global {
|
||||
out = append(out, info)
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
|
||||
return out
|
||||
}
|
||||
|
||||
|
|
@ -133,6 +135,7 @@ func (r *Registry) Loaded(sessionID string) []SkillInfo {
|
|||
out = append(out, info)
|
||||
}
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
|
||||
return out
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package execute
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sort"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
|
@ -45,6 +47,9 @@ func (r *Registry) Discover() error {
|
|||
continue
|
||||
}
|
||||
script := string(data)
|
||||
if !strings.Contains(script, "ollie:prompt") {
|
||||
continue
|
||||
}
|
||||
global[e.Name()] = ParseToolInfo(e.Name(), script)
|
||||
}
|
||||
r.mu.Lock()
|
||||
|
|
@ -63,6 +68,7 @@ func (r *Registry) Summaries() []tools.ToolInfo {
|
|||
Description: info.Description,
|
||||
})
|
||||
}
|
||||
sort.Slice(summaries, func(i, j int) bool { return summaries[i].Name < summaries[j].Name })
|
||||
return summaries
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +127,7 @@ func (r *Registry) Loaded(sessionID string) []tools.ToolInfo {
|
|||
for _, info := range sessionTools {
|
||||
loaded = append(loaded, info)
|
||||
}
|
||||
sort.Slice(loaded, func(i, j int) bool { return loaded[i].Name < loaded[j].Name })
|
||||
return loaded
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ func ParseToolInfo(name, script string) tools.ToolInfo {
|
|||
desc := ExtractShortDescription(prompt)
|
||||
argsSchema := ExtractArgsSchema(script)
|
||||
if argsSchema == nil {
|
||||
argsSchema = json.RawMessage(`{"type":"object","properties":{"tool":{"type":"string"},"args":{"type":"array","items":{"type":"string"}}},"required":["tool","args"]}`)
|
||||
argsSchema = json.RawMessage(`{"type":"object","properties":{}}`)
|
||||
}
|
||||
meta := ExtractMetadata(script)
|
||||
tier := ExtractTier(script)
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ func (e *Server) SetToolRegistry(r *Registry, sessionID string) {
|
|||
}
|
||||
|
||||
// callPromotedTool executes a tool promoted via the registry by running the
|
||||
// script file inside the sandbox, or elevated if the args request it.
|
||||
// script file inside the sandbox, piping the JSON args to stdin.
|
||||
func (e *Server) callPromotedTool(ctx context.Context, tool string, args json.RawMessage) (json.RawMessage, error) {
|
||||
// Resolve script path.
|
||||
if strings.Contains(tool, "/") || strings.Contains(tool, "..") {
|
||||
|
|
@ -282,32 +282,23 @@ func (e *Server) callPromotedTool(ctx context.Context, tool string, args json.Ra
|
|||
}
|
||||
path := filepath.Join(ToolsPath(), tool)
|
||||
|
||||
// Parse args — extract positional args and optional elevated flag.
|
||||
var positional []string
|
||||
// Extract elevated flag (dispatch-level concern, not passed to tool).
|
||||
elevated := false
|
||||
var argMap map[string]interface{}
|
||||
if err := json.Unmarshal(args, &argMap); err == nil {
|
||||
if argsArr, ok := argMap["args"]; ok {
|
||||
if arr, ok := argsArr.([]interface{}); ok {
|
||||
for _, v := range arr {
|
||||
positional = append(positional, fmt.Sprintf("%v", v))
|
||||
}
|
||||
}
|
||||
}
|
||||
if e, ok := argMap["elevated"]; ok {
|
||||
if b, ok := e.(bool); ok {
|
||||
elevated = b
|
||||
}
|
||||
// Remove elevated from the args passed to the tool.
|
||||
delete(argMap, "elevated")
|
||||
args, _ = json.Marshal(argMap)
|
||||
}
|
||||
}
|
||||
|
||||
// Build a shell command that runs the tool script with its args.
|
||||
quoted := make([]string, 0, len(positional)+1)
|
||||
quoted = append(quoted, path)
|
||||
for _, a := range positional {
|
||||
quoted = append(quoted, fmt.Sprintf("%q", a))
|
||||
}
|
||||
code := strings.Join(quoted, " ")
|
||||
// The tool script receives JSON args on stdin.
|
||||
code := path
|
||||
stdinData := string(args)
|
||||
|
||||
var result string
|
||||
var err error
|
||||
|
|
@ -317,7 +308,7 @@ func (e *Server) callPromotedTool(ctx context.Context, tool string, args json.Ra
|
|||
e.wdMu.RUnlock()
|
||||
result, err = e.executeElevated(ctx, code, workDir, 30)
|
||||
} else {
|
||||
result, err = e.executeWithStdin(ctx, code, "bash", 30, "default", false, "")
|
||||
result, err = e.executeWithStdin(ctx, code, "bash", 30, "default", false, stdinData)
|
||||
}
|
||||
if err != nil {
|
||||
return json.Marshal(map[string]interface{}{
|
||||
|
|
@ -332,6 +323,7 @@ func (e *Server) callPromotedTool(ctx context.Context, tool string, args json.Ra
|
|||
|
||||
|
||||
|
||||
|
||||
// Close is called when the session ends. Calls OnClose hook if registered.
|
||||
func (e *Server) Close() {
|
||||
e.cleanupDetached()
|
||||
|
|
|
|||
Reference in New Issue