From d3ac2bef05841e5ff8f1156f00722fef17a247af Mon Sep 17 00:00:00 2001 From: jesse-engineer <784909593@qq.com> Date: Tue, 28 Apr 2026 23:06:44 +0800 Subject: [PATCH] feat(arkruntime): WithResponsesExtraFields for Responses API JSON Add requestOption WithResponsesExtraFields to shallow-merge top-level keys into the wire JSON when the body is *responses.ResponsesRequest. Merge runs in newRequest after all setters, so multimodal preprocessing is included. CreateResponses / CreateResponsesStream usage is unchanged. Made-with: Cursor --- service/arkruntime/client.go | 45 +++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/service/arkruntime/client.go b/service/arkruntime/client.go index f7429636..291725aa 100644 --- a/service/arkruntime/client.go +++ b/service/arkruntime/client.go @@ -18,6 +18,7 @@ import ( "github.com/volcengine/volcengine-go-sdk/service/ark" "github.com/volcengine/volcengine-go-sdk/service/arkruntime/model" + "github.com/volcengine/volcengine-go-sdk/service/arkruntime/model/responses" "github.com/volcengine/volcengine-go-sdk/service/arkruntime/pkg/encryption" "github.com/volcengine/volcengine-go-sdk/service/arkruntime/utils" "github.com/volcengine/volcengine-go-sdk/volcengine" @@ -157,9 +158,10 @@ func (c *Client) protectedRefresh(ctx context.Context, resourceType string, reso } type requestOptions struct { - body interface{} - header http.Header - query url.Values + body interface{} + header http.Header + query url.Values + responsesExtraFields map[string]interface{} } type requestOption func(*requestOptions) @@ -184,6 +186,29 @@ func structToMap(obj interface{}) (map[string]interface{}, error) { return result, nil } +func mergeResponsesRequestBodyIfNeeded(args *requestOptions) error { + if len(args.responsesExtraFields) == 0 { + return nil + } + req, ok := args.body.(*responses.ResponsesRequest) + if !ok { + return fmt.Errorf("WithResponsesExtraFields only applies to *responses.ResponsesRequest body") + } + baseMap, err := structToMap(req) + if err != nil { + return err + } + for k, v := range args.responsesExtraFields { + baseMap[k] = v + } + b, err := json.Marshal(baseMap) + if err != nil { + return err + } + args.body = b + return nil +} + func withContentType(contentType string) requestOption { return func(args *requestOptions) { args.header.Set("Content-Type", contentType) @@ -218,6 +243,16 @@ func WithQuery(key, value string) requestOption { } } +// WithResponsesExtraFields shallow-merges fields into the JSON body when the request body is +// a *responses.ResponsesRequest (Responses API). Merging runs after all requestOption setters +// apply, so it sees the same body that will be sent (including after multimodal preprocessing). +// Keys in fields overwrite top-level keys produced from the protobuf message. +func WithResponsesExtraFields(fields map[string]interface{}) requestOption { + return func(args *requestOptions) { + args.responsesExtraFields = fields + } +} + func (c *Client) newRequest(ctx context.Context, method, url, resourceType, resourceId string, setters ...requestOption) (*http.Request, *model.RequestError) { // Default Options args := &requestOptions{ @@ -238,6 +273,10 @@ func (c *Client) newRequest(ctx context.Context, method, url, resourceType, reso setter(args) } + if errBody := mergeResponsesRequestBodyIfNeeded(args); errBody != nil { + return nil, model.NewRequestError(http.StatusBadRequest, errBody, requestID) + } + errH := c.setCommonHeaders(ctx, args, resourceType, resourceId) if errH != nil { return nil, errH