package basic import ( "bytes" "context" "encoding/json" "fmt" "strings" ) // jsonTool exposes JSON parsing, formatting, validation and serialization for the // agent. `value` is unconstrained in the schema because it is a string for // parse/format/validate and any JSON value for stringify. type jsonTool struct{} // Name returns the tool identifier. func (jsonTool) Name() string { return "json" } // Description explains what the tool does for the model. func (jsonTool) Description() string { return "Parse, format, validate or serialize JSON for structured data handling." } // Parameters returns the tool input JSON Schema. func (jsonTool) Parameters() (map[string]any, error) { return map[string]any{ "type": "object", "properties": map[string]any{ "operation": map[string]any{ "type": "string", "enum": []any{"parse", "format", "validate", "stringify"}, "description": "the operation to perform", }, "value": map[string]any{"description": "input: a JSON string for parse/format/validate, any value for stringify"}, }, "required": []any{"operation"}, }, nil } // Execute runs the requested operation against value. func (jsonTool) Execute(ctx context.Context, args any) (any, error) { if err := ctx.Err(); err != nil { return nil, err } m, err := asMap(args) if err != nil { return nil, err } op, err := reqString(m, "operation") if err != nil { return nil, err } if !hasKey(m, "value") { return nil, fmt.Errorf("basic: missing required argument %q: %w", "value", ErrInvalidArgument) } value := m["value"] switch strings.ToLower(strings.TrimSpace(op)) { case "parse": s, ok := value.(string) if !ok { return nil, fmt.Errorf("basic: argument %q must be a string for parse: %w", "value", ErrInvalidArgument) } var out any if err := json.Unmarshal([]byte(s), &out); err != nil { return nil, fmt.Errorf("basic: invalid json for parse: %w", err) } return map[string]any{"result": out}, nil case "format": s, ok := value.(string) if !ok { return nil, fmt.Errorf("basic: argument %q must be a string for format: %w", "value", ErrInvalidArgument) } var buf bytes.Buffer if err := json.Indent(&buf, []byte(s), "", " "); err != nil { return nil, fmt.Errorf("basic: invalid json for format: %w", err) } return map[string]any{"result": buf.String()}, nil case "validate": s, ok := value.(string) if !ok { return nil, fmt.Errorf("basic: argument %q must be a string for validate: %w", "value", ErrInvalidArgument) } return map[string]any{"valid": json.Valid([]byte(s))}, nil case "stringify": var buf bytes.Buffer enc := json.NewEncoder(&buf) enc.SetIndent("", " ") if err := enc.Encode(value); err != nil { return nil, fmt.Errorf("basic: cannot serialize value: %w", err) } return map[string]any{"result": strings.TrimRight(buf.String(), "\n")}, nil default: return nil, fmt.Errorf("basic: unknown json operation %q: %w", op, ErrUnsupported) } }