Add list tools; normalize tool names and paths in transcript
This commit is contained in:
+57
-14
@@ -181,6 +181,21 @@ func (m *Manager) clientTools(l *live) []mcp.Tool {
|
||||
return m.clientGrep(ctx, raw)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "client_list",
|
||||
Description: listDescription + " It lists a directory on a client Mac, with the byre in its installed Byre.app.",
|
||||
InputSchema: json.RawMessage(`{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"client": {"type": "string", "description": "The client's name from list_clients, or its id when several are connected from that Mac."},
|
||||
"path": {"type": "string", "description": "The directory, absolute or starting with ~/."}
|
||||
},
|
||||
"required": ["client", "path"]
|
||||
}`),
|
||||
Handler: func(ctx context.Context, raw json.RawMessage) (string, error) {
|
||||
return m.clientList(ctx, raw)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "client_hands",
|
||||
Description: "Call one of your hands tools (screen_list, capture, ax_tree, act, browser, chrome) on a client Mac instead of the Mac byre runs on: " +
|
||||
@@ -552,39 +567,67 @@ func (m *Manager) clientGrep(ctx context.Context, raw json.RawMessage) (string,
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("malformed client_grep call: %w", err)
|
||||
}
|
||||
err = clientPath("path", args.Path)
|
||||
path, err := clientShellPath(args.Path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
path := shellQuote(args.Path)
|
||||
rest, ok := strings.CutPrefix(args.Path, "~/")
|
||||
if ok {
|
||||
path = "~/" + shellQuote(rest)
|
||||
}
|
||||
command := clientByre + " grep"
|
||||
flags := ""
|
||||
if args.Glob != "" {
|
||||
command += " --glob " + shellQuote(args.Glob)
|
||||
flags += " --glob " + shellQuote(args.Glob)
|
||||
}
|
||||
if args.IgnoreCase {
|
||||
command += " --ignore-case"
|
||||
flags += " --ignore-case"
|
||||
}
|
||||
if args.FilesOnly {
|
||||
command += " --files-only"
|
||||
flags += " --files-only"
|
||||
}
|
||||
command += " -- " + shellQuote(args.Pattern) + " " + path
|
||||
return m.runClientByre(ctx, args.Client, "grep", flags+" -- "+shellQuote(args.Pattern)+" "+path)
|
||||
}
|
||||
|
||||
type clientListArgs struct {
|
||||
Client string `json:"client"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
func (m *Manager) clientList(ctx context.Context, raw json.RawMessage) (string, error) {
|
||||
args := clientListArgs{}
|
||||
err := json.Unmarshal(raw, &args)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("malformed client_list call: %w", err)
|
||||
}
|
||||
path, err := clientShellPath(args.Path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return m.runClientByre(ctx, args.Client, "list", " "+path)
|
||||
}
|
||||
|
||||
func clientShellPath(p string) (string, error) {
|
||||
err := clientPath("path", p)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
rest, ok := strings.CutPrefix(p, "~/")
|
||||
if ok {
|
||||
return "~/" + shellQuote(rest), nil
|
||||
}
|
||||
return shellQuote(p), nil
|
||||
}
|
||||
|
||||
func (m *Manager) runClientByre(ctx context.Context, client, sub, args string) (string, error) {
|
||||
command := clientByre + " " + sub + args
|
||||
ms := int(fileTimeout.Milliseconds())
|
||||
cctx, cancel := context.WithTimeout(ctx, fileTimeout+replyGrace)
|
||||
defer cancel()
|
||||
reply, err := m.clients.Call(cctx, args.Client, api.ClientRequest{Op: api.Bash, Command: &command, TimeoutMs: &ms})
|
||||
reply, err := m.clients.Call(cctx, client, api.ClientRequest{Op: api.Bash, Command: &command, TimeoutMs: &ms})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if reply.ExitCode == nil || reply.Output == nil {
|
||||
return "", fmt.Errorf("%s's reply has no exit_code or output", args.Client)
|
||||
return "", fmt.Errorf("%s's reply has no exit_code or output", client)
|
||||
}
|
||||
if *reply.ExitCode != 0 {
|
||||
return "", fmt.Errorf("byre grep on %s exited %d: %s", args.Client, *reply.ExitCode, *reply.Output)
|
||||
return "", fmt.Errorf("byre %s on %s exited %d: %s", sub, client, *reply.ExitCode, *reply.Output)
|
||||
}
|
||||
return *reply.Output, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user