package client import ( "encoding/json" "errors" "github.com/google/uuid" ) type ToolHandlerInfo struct { UserId uuid.UUID ImageId uuid.UUID // Pointer because we don't want to copy this around too much. Image *[]byte } type ToolHandler struct { Fn func(info ToolHandlerInfo, args string, call ToolCall) (string, error) } type ToolsHandlers struct { handlers map[string]ToolHandler } var NoToolCallError = errors.New("An assistant tool call with no tool calls was provided.") const NonExistantTool = "This tool does not exist" func (handler ToolsHandlers) Handle(info ToolHandlerInfo, toolCallMessage ToolCall) ChatUserToolResponse { fnName := toolCallMessage.Function.Name arguments := toolCallMessage.Function.Arguments responseMessage := ChatUserToolResponse{ Role: "tool", Name: fnName, ToolCallId: toolCallMessage.Id, } fnHandler, exists := handler.handlers[fnName] if !exists { responseMessage.Content = NonExistantTool return responseMessage } res, err := fnHandler.Fn(info, arguments, toolCallMessage) if err != nil { responseMessage.Content = err.Error() } else { responseMessage.Content = res } return responseMessage } func (handler *ToolsHandlers) AddTool(name string, fn func(info ToolHandlerInfo, args string, call ToolCall) (any, error)) { handler.handlers[name] = ToolHandler{ Fn: func(info ToolHandlerInfo, args string, call ToolCall) (string, error) { res, err := fn(info, args, call) if err != nil { return "", err } marshalledRes, err := json.Marshal(res) if err != nil { return "", err } return string(marshalledRes), nil }, } }