Files

78 lines
2.2 KiB
Go

package basic
import (
"context"
"fmt"
"time"
)
// datetime returns the current time, optionally formatted with a Go reference
// layout and rendered in a named IANA timezone.
type datetime struct{}
const (
// defaultDTFormat is the layout used when the caller supplies none.
defaultDTFormat = time.RFC3339
// defaultDTZone is the timezone used when the caller supplies none.
defaultDTZone = "UTC"
// maxDTFormatLen bounds a layout string to guard against absurd input.
maxDTFormatLen = 128
// maxDTZoneLen bounds a timezone name to guard against absurd input.
maxDTZoneLen = 64
)
// Name returns the tool identifier.
func (datetime) Name() string { return "datetime" }
// Description explains what the tool does for the model.
func (datetime) Description() string {
return "Return the current time, formatted with a Go reference layout and rendered in a named IANA timezone."
}
// Parameters returns the tool input JSON Schema.
func (datetime) Parameters() (map[string]any, error) {
return map[string]any{
"type": "object",
"properties": map[string]any{
"format": map[string]any{"type": "string", "description": "Go reference layout, e.g. 2006-01-02 15:04:05"},
"timezone": map[string]any{"type": "string", "description": "IANA timezone name, e.g. Asia/Shanghai"},
},
}, nil
}
// Execute returns the current time in the requested format and timezone.
func (datetime) 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
}
layout, err := optString(m, "format", defaultDTFormat)
if err != nil {
return nil, err
}
if len(layout) > maxDTFormatLen {
return nil, fmt.Errorf("basic: layout too long: %w", ErrInvalidArgument)
}
zone, err := optString(m, "timezone", defaultDTZone)
if err != nil {
return nil, err
}
if len(zone) > maxDTZoneLen {
return nil, fmt.Errorf("basic: timezone name too long: %w", ErrInvalidArgument)
}
loc, err := time.LoadLocation(zone)
if err != nil {
return nil, fmt.Errorf("basic: invalid timezone %q: %w", zone, err)
}
now := time.Now().In(loc)
return map[string]any{
"now": now.Format(layout),
"unix": now.Unix(),
"timezone": zone,
"format": layout,
}, nil
}