package standard import ( "fmt" "io" "maps" "net/http" "strings" "reichard.io/poiesis/internal/runtime/pkg/builtin" ) type FetchArgs struct { Input string `json:"input"` Init *FetchOptions `json:"init,omitempty"` } type FetchOptions struct { Method string `json:"method,omitempty"` Headers map[string]string `json:"headers,omitempty"` Body *string `json:"body,omitempty"` } func (o *FetchOptions) Defaults() *FetchOptions { if o.Method == "" { o.Method = "GET" } return o } type FetchResult struct { OK bool `json:"ok"` Status int `json:"status"` Body string `json:"body"` Headers map[string]string `json:"headers"` } type AddArgs struct { A int `json:"a"` B int `json:"b"` } type GreetArgs struct { Name string `json:"name"` } func Fetch(args FetchArgs) (*FetchResult, error) { method := "GET" headers := make(map[string]string) if args.Init != nil { method = args.Init.Method if args.Init.Headers != nil { maps.Copy(headers, args.Init.Headers) } } req, err := http.NewRequest(method, args.Input, nil) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } for k, v := range headers { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, fmt.Errorf("failed to fetch: %w", err) } defer func() { _ = resp.Body.Close() }() body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read body: %w", err) } resultHeaders := make(map[string]string) for key, values := range resp.Header { if len(values) > 0 { val := values[0] resultHeaders[key] = val resultHeaders[strings.ToLower(key)] = val } } return &FetchResult{ OK: resp.StatusCode >= 200 && resp.StatusCode < 300, Status: resp.StatusCode, Body: string(body), Headers: resultHeaders, }, nil } func add(args AddArgs) int { return args.A + args.B } func greet(args GreetArgs) string { return fmt.Sprintf("Hello, %s!", args.Name) } func init() { builtin.RegisterBuiltin[FetchArgs, *FetchResult]("fetch", Fetch, builtin.WithPromise()) builtin.RegisterBuiltin[AddArgs, int]("add", add) builtin.RegisterBuiltin[GreetArgs, string]("greet", greet) }