coze-studio/backend/api/handler/coze/workflow_service.go

1131 lines
28 KiB
Go

/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Code generated by hertz generator.
package coze
import (
"context"
"errors"
"fmt"
"io"
"github.com/cloudwego/eino/schema"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/protocol/consts"
"github.com/cloudwego/hertz/pkg/protocol/sse"
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/workflow"
appworkflow "github.com/coze-dev/coze-studio/backend/application/workflow"
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
"github.com/coze-dev/coze-studio/backend/pkg/logs"
"github.com/coze-dev/coze-studio/backend/pkg/sonic"
)
// CreateWorkflow .
// @router /api/workflow_api/create [POST]
func CreateWorkflow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.CreateWorkflowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.CreateWorkflow(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetCanvasInfo .
// @router /api/workflow_api/canvas [POST]
func GetCanvasInfo(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetCanvasInfoRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetCanvasInfo(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// SaveWorkflow .
// @router /api/workflow_api/save [POST]
func SaveWorkflow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.SaveWorkflowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.SaveWorkflow(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// UpdateWorkflowMeta .
// @router /api/workflow_api/update_meta [POST]
func UpdateWorkflowMeta(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.UpdateWorkflowMetaRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.UpdateWorkflowMeta(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// DeleteWorkflow .
// @router /api/workflow_api/delete [POST]
func DeleteWorkflow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.DeleteWorkflowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.DeleteWorkflow(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// BatchDeleteWorkflow .
// @router /api/workflow_api/batch_delete [POST]
func BatchDeleteWorkflow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.BatchDeleteWorkflowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.BatchDeleteWorkflow(ctx, &req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
c.JSON(consts.StatusOK, resp)
}
// GetDeleteStrategy .
// @router /api/workflow_api/delete_strategy [POST]
func GetDeleteStrategy(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetDeleteStrategyRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.GetDeleteStrategyResponse)
c.JSON(consts.StatusOK, resp)
}
// PublishWorkflow .
// @router /api/workflow_api/publish [POST]
func PublishWorkflow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.PublishWorkflowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.PublishWorkflow(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// CopyWorkflow .
// @router /api/workflow_api/copy [POST]
func CopyWorkflow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.CopyWorkflowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.CopyWorkflow(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// CopyWkTemplateApi .
// @router /api/workflow_api/copy_wk_template [POST]
func CopyWkTemplateApi(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.CopyWkTemplateApiRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.CopyWkTemplateApi(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetReleasedWorkflows .
// @router /api/workflow_api/released_workflows [POST]
func GetReleasedWorkflows(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetReleasedWorkflowsRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.GetReleasedWorkflowsResponse)
c.JSON(consts.StatusOK, resp)
}
// GetWorkflowReferences
// @router /api/workflow_api/workflow_references [POST]
func GetWorkflowReferences(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetWorkflowReferencesRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetWorkflowReferences(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetWorkFlowList .
// @router /api/workflow_api/workflow_list [POST]
func GetWorkFlowList(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetWorkFlowListRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.ListWorkflow(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// QueryWorkflowNodeTypes .
// @router /api/workflow_api/node_type [POST]
func QueryWorkflowNodeTypes(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.QueryWorkflowNodeTypeRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.QueryWorkflowNodeTypes(ctx, &req)
if err != nil {
c.String(consts.StatusInternalServerError, err.Error())
return
}
c.JSON(consts.StatusOK, resp)
}
// NodeTemplateList .
// @router /api/workflow_api/node_template_list [POST]
func NodeTemplateList(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.NodeTemplateListRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetNodeTemplateList(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// NodePanelSearch .
// @router /api/workflow_api/node_panel_search [POST]
func NodePanelSearch(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.NodePanelSearchRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.NodePanelSearchResponse)
c.JSON(consts.StatusOK, resp)
}
// GetLLMNodeFCSettingsMerged .
// @router /api/workflow_api/llm_fc_setting_merged [POST]
func GetLLMNodeFCSettingsMerged(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetLLMNodeFCSettingsMergedRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetLLMNodeFCSettingsMerged(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetLLMNodeFCSettingDetail .
// @router /api/workflow_api/llm_fc_setting_detail [POST]
func GetLLMNodeFCSettingDetail(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetLLMNodeFCSettingDetailRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetLLMNodeFCSettingDetail(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// WorkFlowTestRun .
// @router /api/workflow_api/test_run [POST]
func WorkFlowTestRun(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.WorkFlowTestRunRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.TestRun(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// WorkFlowTestResume .
// @router /api/workflow_api/test_resume [POST]
func WorkFlowTestResume(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.WorkflowTestResumeRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.TestResume(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// CancelWorkFlow .
// @router /api/workflow_api/cancel [POST]
func CancelWorkFlow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.CancelWorkFlowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.Cancel(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetWorkFlowProcess .
// @router /api/workflow_api/get_process [GET]
func GetWorkFlowProcess(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetWorkflowProcessRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetProcess(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetNodeExecuteHistory .
// @router /api/workflow_api/get_node_execute_history [GET]
func GetNodeExecuteHistory(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetNodeExecuteHistoryRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetNodeExecuteHistory(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetApiDetail .
// @router /api/workflow_api/apiDetail [GET]
func GetApiDetail(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetApiDetailRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
toolDetailInfo, err := appworkflow.SVC.GetApiDetail(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
response := map[string]interface{}{
"data": toolDetailInfo,
"code": 0,
"msg": "",
}
c.JSON(consts.StatusOK, response)
}
// WorkflowNodeDebugV2 .
// @router /api/workflow_api/nodeDebug [POST]
func WorkflowNodeDebugV2(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.WorkflowNodeDebugV2Request
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.NodeDebug(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// SignImageURL .
// @router /api/workflow_api/sign_image_url [POST]
func SignImageURL(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.SignImageURLRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.SignImageURL(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// CreateProjectConversationDef .
// @router /api/workflow_api/project_conversation/create [POST]
func CreateProjectConversationDef(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.CreateProjectConversationDefRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.CreateProjectConversationDefResponse)
c.JSON(consts.StatusOK, resp)
}
// UpdateProjectConversationDef .
// @router /api/workflow_api/project_conversation/update [POST]
func UpdateProjectConversationDef(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.UpdateProjectConversationDefRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.UpdateProjectConversationDefResponse)
c.JSON(consts.StatusOK, resp)
}
// DeleteProjectConversationDef .
// @router /api/workflow_api/project_conversation/delete [POST]
func DeleteProjectConversationDef(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.DeleteProjectConversationDefRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.DeleteProjectConversationDefResponse)
c.JSON(consts.StatusOK, resp)
}
// ListProjectConversationDef .
// @router /api/workflow_api/project_conversation/list [GET]
func ListProjectConversationDef(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.ListProjectConversationRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.ListProjectConversationResponse)
c.JSON(consts.StatusOK, resp)
}
// ListRootSpans .
// @router /api/workflow_api/list_spans [POST]
func ListRootSpans(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.ListRootSpansRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.ListRootSpansResponse)
c.JSON(consts.StatusOK, resp)
}
// GetTraceSDK .
// @router /api/workflow_api/get_trace [POST]
func GetTraceSDK(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetTraceSDKRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.GetTraceSDKResponse)
c.JSON(consts.StatusOK, resp)
}
// GetWorkflowDetail .
// @router /api/workflow_api/workflow_detail [POST]
func GetWorkflowDetail(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetWorkflowDetailRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
workflowDetailDataList, err := appworkflow.SVC.GetWorkflowDetail(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
response := map[string]any{
"data": workflowDetailDataList,
"code": 0,
"message": "",
}
c.JSON(consts.StatusOK, response)
}
// GetWorkflowDetailInfo .
// @router /api/workflow_api/workflow_detail_info [POST]
func GetWorkflowDetailInfo(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetWorkflowDetailInfoRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
workflowDetailInfoDataList, err := appworkflow.SVC.GetWorkflowDetailInfo(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
response := map[string]any{
"data": workflowDetailInfoDataList,
"code": 0,
"message": "",
}
c.JSON(consts.StatusOK, response)
}
// ValidateTree .
// @router /api/workflow_api/validate_tree [POST]
func ValidateTree(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.ValidateTreeRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.ValidateTree(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetChatFlowRole .
// @router /api/workflow_api/chat_flow_role/get [GET]
func GetChatFlowRole(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetChatFlowRoleRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.GetChatFlowRoleResponse)
c.JSON(consts.StatusOK, resp)
}
// CreateChatFlowRole .
// @router /api/workflow_api/chat_flow_role/create [POST]
func CreateChatFlowRole(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.CreateChatFlowRoleRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.CreateChatFlowRoleResponse)
c.JSON(consts.StatusOK, resp)
}
// DeleteChatFlowRole .
// @router /api/workflow_api/chat_flow_role/delete [POST]
func DeleteChatFlowRole(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.DeleteChatFlowRoleRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.DeleteChatFlowRoleResponse)
c.JSON(consts.StatusOK, resp)
}
// ListPublishWorkflow .
// @router /api/workflow_api/list_publish_workflow [POST]
func ListPublishWorkflow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.ListPublishWorkflowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.ListPublishWorkflowResponse)
c.JSON(consts.StatusOK, resp)
}
// GetWorkflowUploadAuthToken .
// @router /api/workflow_api/upload/auth_token [POST]
func GetWorkflowUploadAuthToken(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetUploadAuthTokenRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetWorkflowUploadAuthToken(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
func preprocessWorkflowRequestBody(_ context.Context, c *app.RequestContext) error {
// Read the raw request body
rawData, err := c.Request.BodyE()
if err != nil {
return fmt.Errorf("failed to read request body: %w", err)
}
// Unmarshal into a temporary map
var bodyData map[string]interface{}
if err = sonic.Unmarshal(rawData, &bodyData); err != nil {
return fmt.Errorf("failed to unmarshal request body: %w", err)
}
// Process 'parameters' field
if parameters, ok := bodyData["parameters"]; ok {
if _, isString := parameters.(string); !isString {
// It's not a string, needs modification.
paramsBytes, marshalErr := sonic.Marshal(parameters)
if marshalErr != nil {
return fmt.Errorf("failed to marshal parameters: %w", marshalErr)
}
bodyData["parameters"] = string(paramsBytes)
newRawData, err := sonic.Marshal(bodyData)
if err != nil {
return fmt.Errorf("failed to marshal modified body: %w", err)
}
c.Request.SetBodyRaw(newRawData)
return nil
}
}
return nil
}
// OpenAPIRunFlow .
// @router /v1/workflow/run [POST]
func OpenAPIRunFlow(ctx context.Context, c *app.RequestContext) {
var err error
if err = preprocessWorkflowRequestBody(ctx, c); err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
var req workflow.OpenAPIRunFlowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.OpenAPIRun(ctx, &req)
if err != nil {
var se vo.WorkflowError
if errors.As(err, &se) {
resp = new(workflow.OpenAPIRunFlowResponse)
resp.Code = int64(se.OpenAPICode())
resp.Msg = ptr.Of(se.Msg())
debugURL := se.DebugURL()
if debugURL != "" {
resp.DebugUrl = ptr.Of(debugURL)
}
c.JSON(consts.StatusOK, resp)
return
}
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
type streamRunData struct {
Content *string `json:"content,omitempty"`
ContentType *string `json:"content_type,omitempty"`
NodeSeqID *string `json:"node_seq_id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
NodeIsFinish *bool `json:"node_is_finish,omitempty"`
NodeType *string `json:"node_type,omitempty"`
NodeTitle *string `json:"node_title,omitempty"`
Token *int64 `json:"token,omitempty"`
DebugURL *string `json:"debug_url,omitempty"`
ErrorCode *int64 `json:"error_code,omitempty"`
ErrorMessage *string `json:"error_message,omitempty"`
InterruptData *interruptData `json:"interrupt_data,omitempty"`
}
type interruptData struct {
EventID string `json:"event_id"`
Type int64 `json:"type"`
Data string `json:"data"`
}
func convertStreamRunData(msg *workflow.OpenAPIStreamRunFlowResponse) *streamRunData {
var ie *interruptData
if msg.InterruptData != nil {
ie = &interruptData{
EventID: msg.InterruptData.EventID,
Type: int64(msg.InterruptData.Type),
Data: msg.InterruptData.InData,
}
}
return &streamRunData{
Content: msg.Content,
ContentType: msg.ContentType,
NodeSeqID: msg.NodeSeqID,
NodeID: msg.NodeID,
NodeIsFinish: msg.NodeIsFinish,
NodeType: msg.NodeType,
NodeTitle: msg.NodeTitle,
Token: msg.Token,
DebugURL: msg.DebugUrl,
ErrorCode: msg.ErrorCode,
ErrorMessage: msg.ErrorMessage,
InterruptData: ie,
}
}
func sendStreamRunSSE(ctx context.Context, w *sse.Writer, sr *schema.StreamReader[*workflow.OpenAPIStreamRunFlowResponse]) {
defer func() {
_ = w.Close()
sr.Close()
}()
for {
msg, err := sr.Recv()
if err != nil {
if errors.Is(err, io.EOF) {
// finish
break
}
event := &sse.Event{
Type: "error",
Data: []byte(err.Error()),
}
if err = w.Write(event); err != nil {
logs.CtxErrorf(ctx, "publish stream event failed, err:%v", err)
}
return
}
converted := convertStreamRunData(msg)
msgBytes, err := sonic.Marshal(converted)
if err != nil {
event := &sse.Event{
Type: "error",
Data: []byte(err.Error()),
}
if err = w.Write(event); err != nil {
logs.CtxErrorf(ctx, "publish stream event failed, err:%v", err)
}
return
}
event := &sse.Event{
ID: msg.ID,
Type: msg.Event,
Data: msgBytes,
}
if err = w.Write(event); err != nil {
logs.CtxErrorf(ctx, "publish stream event failed, err:%v", err)
return
}
}
}
// OpenAPIStreamRunFlow .
// @router /v1/workflow/stream_run [POST]
func OpenAPIStreamRunFlow(ctx context.Context, c *app.RequestContext) {
var err error
if err = preprocessWorkflowRequestBody(ctx, c); err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
var req workflow.OpenAPIRunFlowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
w := sse.NewWriter(c)
c.SetContentType("text/event-stream; charset=utf-8")
c.Response.Header.Set("Cache-Control", "no-cache")
c.Response.Header.Set("Connection", "keep-alive")
c.Response.Header.Set("Access-Control-Allow-Origin", "*")
sr, err := appworkflow.SVC.OpenAPIStreamRun(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
sendStreamRunSSE(ctx, w, sr)
}
// OpenAPIStreamResumeFlow .
// @router /v1/workflow/stream_resume [POST]
func OpenAPIStreamResumeFlow(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.OpenAPIStreamResumeFlowRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
w := sse.NewWriter(c)
c.SetContentType("text/event-stream; charset=utf-8")
c.Response.Header.Set("Cache-Control", "no-cache")
c.Response.Header.Set("Connection", "keep-alive")
c.Response.Header.Set("Access-Control-Allow-Origin", "*")
sr, err := appworkflow.SVC.OpenAPIStreamResume(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
sendStreamRunSSE(ctx, w, sr)
}
// OpenAPIGetWorkflowRunHistory .
// @router /v1/workflow/get_run_history [GET]
func OpenAPIGetWorkflowRunHistory(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetWorkflowRunHistoryRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.OpenAPIGetWorkflowRunHistory(ctx, &req)
if err != nil {
var se vo.WorkflowError
if errors.As(err, &se) {
resp = new(workflow.GetWorkflowRunHistoryResponse)
resp.Code = ptr.Of(int64(se.OpenAPICode()))
resp.Msg = ptr.Of(se.Msg())
c.JSON(consts.StatusOK, resp)
return
}
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// OpenAPIChatFlowRun .
// @router /v1/workflows/chat [POST]
func OpenAPIChatFlowRun(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.ChatFlowRunRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.ChatFlowRunResponse)
c.JSON(consts.StatusOK, resp)
}
// OpenAPIGetWorkflowInfo .
// @router /v1/workflows/:workflow_id [GET]
func OpenAPIGetWorkflowInfo(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.OpenAPIGetWorkflowInfoRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp := new(workflow.OpenAPIGetWorkflowInfoResponse)
c.JSON(consts.StatusOK, resp)
}
// GetHistorySchema .
// @router /api/workflow_api/history_schema [POST]
func GetHistorySchema(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetHistorySchemaRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetHistorySchema(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
// GetExampleWorkFlowList .
// @router /api/workflow_api/example_workflow_list [POST]
func GetExampleWorkFlowList(ctx context.Context, c *app.RequestContext) {
var err error
var req workflow.GetExampleWorkFlowListRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := appworkflow.SVC.GetExampleWorkFlowList(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}