78 lines
2.2 KiB
Go
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
|
|
}
|