Let task agents use client Macs directly: bash, copy and hands

This commit is contained in:
Ian Gulliver
2026-10-17 23:45:31 -07:00
parent 8d9ba10849
commit 9b79ade073
25 changed files with 1382 additions and 952 deletions
+36 -16
View File
@@ -13,6 +13,41 @@ type Tool struct {
Description string
InputSchema json.RawMessage
Handler func(ctx context.Context, args json.RawMessage) (string, error)
Rich func(ctx context.Context, args json.RawMessage) Result
}
type Content struct {
Type string `json:"type"`
Text string `json:"text"`
Data string `json:"data"`
MimeType string `json:"mimeType"`
}
func (c Content) MarshalJSON() ([]byte, error) {
if c.Type == "image" {
return json.Marshal(map[string]string{"type": c.Type, "data": c.Data, "mimeType": c.MimeType})
}
return json.Marshal(map[string]string{"type": c.Type, "text": c.Text})
}
type Result struct {
Content []Content `json:"content"`
IsError bool `json:"isError,omitempty"`
}
func TextResult(text string, isError bool) Result {
return Result{Content: []Content{{Type: "text", Text: text}}, IsError: isError}
}
func (t Tool) Call(ctx context.Context, args json.RawMessage) Result {
if t.Rich != nil {
return t.Rich(ctx, args)
}
text, err := t.Handler(ctx, args)
if err != nil {
return TextResult(err.Error(), true)
}
return TextResult(text, false)
}
type Server struct {
@@ -52,16 +87,6 @@ type toolDesc struct {
InputSchema json.RawMessage `json:"inputSchema"`
}
type content struct {
Type string `json:"type"`
Text string `json:"text"`
}
type callResult struct {
Content []content `json:"content"`
IsError bool `json:"isError,omitempty"`
}
func (s *Server) Tool(name string) (Tool, bool) {
for _, t := range s.Tools {
if t.Name == name {
@@ -128,10 +153,5 @@ func (s *Server) call(ctx context.Context, params json.RawMessage) (any, *rpcErr
return nil, &rpcError{Code: -32602, Message: fmt.Sprintf("unknown tool: %s", p.Name)}
}
text, err := t.Handler(ctx, p.Arguments)
if err != nil {
return callResult{Content: []content{{Type: "text", Text: err.Error()}}, IsError: true}, nil
}
return callResult{Content: []content{{Type: "text", Text: text}}}, nil
return t.Call(ctx, p.Arguments), nil
}