feat(api): 统一官方兼容接口响应协议
兼容接口现在以入口协议作为最终响应协议,同协议保留官方 Wire 响应,跨协议统一转换成功、任务状态与错误结构。 同时修正异步提交状态边界,持久化兼容公开任务标识和官方提交响应,并新增迁移、流式响应及协议契约测试。 验证:go vet ./...;go test ./...;govulncheck ./...;pnpm lint;pnpm test;pnpm build;pnpm audit --audit-level high;pnpm openapi;全部 CI 脚本。
This commit is contained in:
@@ -80,7 +80,18 @@ func (c KelingClient) runVideo(ctx context.Context, request Request, token strin
|
||||
}()
|
||||
|
||||
if upstreamTaskID == "" {
|
||||
submitResult, requestID, err := c.postJSON(ctx, request, prepared.Endpoint, token, prepared.Payload)
|
||||
if err := notifySubmissionStarted(request); err != nil {
|
||||
return Response{}, err
|
||||
}
|
||||
submitResult, requestID, submitWire, err := c.postJSON(ctx, request, prepared.Endpoint, token, prepared.Payload)
|
||||
if notifyErr := notifyWireResponse(request, submitWire); notifyErr != nil {
|
||||
return Response{}, notifyErr
|
||||
}
|
||||
if err == nil || ErrorResponseMetadata(err).StatusCode > 0 {
|
||||
if notifyErr := notifyResponseReceived(request); notifyErr != nil {
|
||||
return Response{}, notifyErr
|
||||
}
|
||||
}
|
||||
submitRequestID = requestID
|
||||
if err != nil {
|
||||
return Response{}, annotateResponseError(err, submitRequestID, submitStartedAt, time.Now())
|
||||
@@ -122,6 +133,11 @@ func (c KelingClient) runVideo(ctx context.Context, request Request, token strin
|
||||
return Response{}, annotateResponseError(err, requestID, pollStartedAt, pollFinishedAt)
|
||||
}
|
||||
lastResult = pollResult
|
||||
if request.OnRemoteTaskPolled != nil {
|
||||
if err := request.OnRemoteTaskPolled(upstreamTaskID, pollResult); err != nil {
|
||||
return Response{}, err
|
||||
}
|
||||
}
|
||||
|
||||
switch kelingTaskStatus(pollResult) {
|
||||
case "succeed":
|
||||
@@ -176,7 +192,18 @@ func (c KelingClient) runTaskAPIVideo(ctx context.Context, request Request, toke
|
||||
if err != nil {
|
||||
return Response{}, err
|
||||
}
|
||||
submitResult, requestID, err := c.postJSONAt(ctx, request, taskAPIBaseURL, endpoint, token, payload)
|
||||
if err := notifySubmissionStarted(request); err != nil {
|
||||
return Response{}, err
|
||||
}
|
||||
submitResult, requestID, submitWire, err := c.postJSONAt(ctx, request, taskAPIBaseURL, endpoint, token, payload, ProtocolKlingV2Omni)
|
||||
if notifyErr := notifyWireResponse(request, submitWire); notifyErr != nil {
|
||||
return Response{}, notifyErr
|
||||
}
|
||||
if err == nil || ErrorResponseMetadata(err).StatusCode > 0 {
|
||||
if notifyErr := notifyResponseReceived(request); notifyErr != nil {
|
||||
return Response{}, notifyErr
|
||||
}
|
||||
}
|
||||
submitRequestID = requestID
|
||||
if err != nil {
|
||||
return Response{}, annotateResponseError(err, submitRequestID, submitStartedAt, time.Now())
|
||||
@@ -224,6 +251,11 @@ func (c KelingClient) runTaskAPIVideo(ctx context.Context, request Request, toke
|
||||
if err != nil {
|
||||
return Response{}, annotateResponseError(err, requestID, pollStartedAt, pollFinishedAt)
|
||||
}
|
||||
if request.OnRemoteTaskPolled != nil {
|
||||
if err := request.OnRemoteTaskPolled(upstreamTaskID, pollResult); err != nil {
|
||||
return Response{}, err
|
||||
}
|
||||
}
|
||||
|
||||
task := kelingTaskAPITask(pollResult, upstreamTaskID)
|
||||
lastStatus = strings.ToLower(strings.TrimSpace(stringFromAny(task["status"])))
|
||||
@@ -567,31 +599,31 @@ func (c KelingClient) kelingOmniElementList(ctx context.Context, request Request
|
||||
return elements, createdIDs, nil
|
||||
}
|
||||
|
||||
func (c KelingClient) postJSON(ctx context.Context, request Request, path string, token string, body map[string]any) (map[string]any, string, error) {
|
||||
return c.postJSONAt(ctx, request, request.Candidate.BaseURL, path, token, body)
|
||||
func (c KelingClient) postJSON(ctx context.Context, request Request, path string, token string, body map[string]any) (map[string]any, string, *WireResponse, error) {
|
||||
return c.postJSONAt(ctx, request, request.Candidate.BaseURL, path, token, body, ProtocolKlingV1Omni)
|
||||
}
|
||||
|
||||
func (c KelingClient) postJSONAt(ctx context.Context, request Request, baseURL string, path string, token string, body map[string]any) (map[string]any, string, error) {
|
||||
func (c KelingClient) postJSONAt(ctx context.Context, request Request, baseURL string, path string, token string, body map[string]any, protocol string) (map[string]any, string, *WireResponse, error) {
|
||||
raw, _ := json.Marshal(body)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, joinURL(baseURL, path), bytes.NewReader(raw))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
return nil, "", nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
resp, err := httpClient(request.HTTPClient, c.HTTPClient).Do(req)
|
||||
if err != nil {
|
||||
return nil, "", &ClientError{Code: "network", Message: err.Error(), Retryable: true}
|
||||
return nil, "", nil, &ClientError{Code: "network", Message: err.Error(), Retryable: true}
|
||||
}
|
||||
requestID := requestIDFromHTTPResponse(resp)
|
||||
result, err := decodeHTTPResponse(resp)
|
||||
result, wire, err := decodeHTTPResponseForProtocol(resp, protocol)
|
||||
if err != nil {
|
||||
return result, requestID, err
|
||||
return result, requestID, wire, err
|
||||
}
|
||||
if code := intFromAny(result["code"]); code != 0 {
|
||||
return result, requestID, &ClientError{Code: kelingEnvelopeErrorCode(result), Message: kelingEnvelopeErrorMessage(result), RequestID: firstNonEmpty(requestID, stringFromAny(result["request_id"])), Retryable: false}
|
||||
return result, requestID, wire, &ClientError{Code: kelingEnvelopeErrorCode(result), Message: kelingEnvelopeErrorMessage(result), RequestID: firstNonEmpty(requestID, stringFromAny(result["request_id"])), Retryable: false, Wire: wire}
|
||||
}
|
||||
return result, firstNonEmpty(requestID, stringFromAny(result["request_id"])), nil
|
||||
return result, firstNonEmpty(requestID, stringFromAny(result["request_id"])), wire, nil
|
||||
}
|
||||
|
||||
func (c KelingClient) getJSON(ctx context.Context, request Request, path string, token string) (map[string]any, string, error) {
|
||||
@@ -663,7 +695,7 @@ func (c KelingClient) cleanupKelingElements(ctx context.Context, request Request
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
_, _, _ = c.postJSON(ctx, request, "/general/delete-elements", token, map[string]any{"element_id": id})
|
||||
_, _, _, _ = c.postJSON(ctx, request, "/general/delete-elements", token, map[string]any{"element_id": id})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user