Files
Cyrene_v2/plugins/tools/basic/json.go
T

96 lines
2.9 KiB
Go

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)
}
}