112 lines
3.7 KiB
Go
112 lines
3.7 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.
|
|
*/
|
|
package plugin
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/cloudwego/eino/compose"
|
|
|
|
workflow3 "github.com/coze-dev/coze-studio/backend/api/model/workflow"
|
|
crossplugin "github.com/coze-dev/coze-studio/backend/crossdomain/plugin"
|
|
"github.com/coze-dev/coze-studio/backend/crossdomain/plugin/consts"
|
|
"github.com/coze-dev/coze-studio/backend/crossdomain/plugin/model"
|
|
workflowModel "github.com/coze-dev/coze-studio/backend/crossdomain/workflow/model"
|
|
"github.com/coze-dev/coze-studio/backend/domain/workflow"
|
|
entity2 "github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
|
|
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
|
|
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
|
"github.com/coze-dev/coze-studio/backend/pkg/lang/conv"
|
|
"github.com/coze-dev/coze-studio/backend/pkg/sonic"
|
|
"github.com/coze-dev/coze-studio/backend/types/errno"
|
|
)
|
|
|
|
func ExecutePlugin(ctx context.Context, input map[string]any, pe *vo.PluginEntity,
|
|
toolID int64, cfg workflowModel.ExecuteConfig) (map[string]any, error) {
|
|
args, err := sonic.MarshalString(input)
|
|
if err != nil {
|
|
return nil, vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
|
}
|
|
|
|
var uID string
|
|
if cfg.ConnectorUID != "" {
|
|
uID = cfg.ConnectorUID
|
|
} else {
|
|
uID = conv.Int64ToStr(cfg.Operator)
|
|
}
|
|
|
|
req := &model.ExecuteToolRequest{
|
|
UserID: uID,
|
|
PluginID: pe.PluginID,
|
|
ToolID: toolID,
|
|
ExecScene: consts.ExecSceneOfWorkflow,
|
|
ArgumentsInJson: args,
|
|
ExecDraftTool: pe.PluginVersion == nil || *pe.PluginVersion == "0",
|
|
PluginFrom: pe.PluginFrom,
|
|
}
|
|
execOpts := []model.ExecuteToolOpt{
|
|
model.WithInvalidRespProcessStrategy(consts.InvalidResponseProcessStrategyOfReturnDefault),
|
|
}
|
|
|
|
if pe.PluginVersion != nil {
|
|
execOpts = append(execOpts, model.WithToolVersion(*pe.PluginVersion))
|
|
}
|
|
|
|
r, err := crossplugin.DefaultSVC().ExecuteTool(ctx, req, execOpts...)
|
|
if err != nil {
|
|
if extra, ok := compose.IsInterruptRerunError(err); ok {
|
|
pluginTIE, ok := extra.(*model.ToolInterruptEvent)
|
|
if !ok {
|
|
return nil, vo.WrapError(errno.ErrPluginAPIErr, fmt.Errorf("expects ToolInterruptEvent, got %T", extra))
|
|
}
|
|
|
|
var eventType workflow3.EventType
|
|
switch pluginTIE.Event {
|
|
case consts.InterruptEventTypeOfToolNeedOAuth:
|
|
eventType = workflow3.EventType_WorkflowOauthPlugin
|
|
default:
|
|
return nil, vo.WrapError(errno.ErrPluginAPIErr,
|
|
fmt.Errorf("unsupported interrupt event type: %s", pluginTIE.Event))
|
|
}
|
|
|
|
id, err := workflow.GetRepository().GenID(ctx)
|
|
if err != nil {
|
|
return nil, vo.WrapError(errno.ErrIDGenError, err)
|
|
}
|
|
|
|
ie := &entity2.InterruptEvent{
|
|
ID: id,
|
|
InterruptData: pluginTIE.ToolNeedOAuth.Message,
|
|
EventType: eventType,
|
|
}
|
|
|
|
// temporarily replace interrupt with real error, until frontend can handle plugin oauth interrupt
|
|
interruptData := ie.InterruptData
|
|
return nil, vo.NewError(errno.ErrAuthorizationRequired, errorx.KV("extra", interruptData))
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
var output map[string]any
|
|
err = sonic.UnmarshalString(r.TrimmedResp, &output)
|
|
if err != nil {
|
|
return nil, vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
|
}
|
|
|
|
return output, nil
|
|
}
|