增强插件系统:添加操作参数信息获取功能

- 在插件接口中新增 GetOperationInfo 和 GetAllOperations 方法,支持获取特定操作及所有操作的参数信息。
- 更新 PluginHelper 以实现获取操作参数信息的功能,提升插件的可用性和灵活性。
- 在日志插件中实现操作信息获取,展示如何使用新方法获取操作的详细参数信息。
- 示例程序中添加新的选项,展示如何获取插件操作的参数信息。

此更新提升了插件系统的可扩展性和易用性,便于开发者更好地管理和使用插件功能。
This commit is contained in:
2025-03-14 12:32:02 +08:00
parent b6bf2c5699
commit 2e29253909
6 changed files with 538 additions and 3 deletions

View File

@@ -43,6 +43,10 @@ type Plugin interface {
// params: 操作所需的参数
// 返回操作结果和可能的错误
Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error)
// GetOperationInfo 获取操作的参数信息
GetOperationInfo(operation string) (map[string]interface{}, error)
// GetAllOperations 获取所有操作及其参数信息
GetAllOperations() map[string]map[string]interface{}
}
// PluginHelper 插件辅助器
@@ -469,6 +473,169 @@ func convertParamValue(value interface{}, targetType reflect.Type) (reflect.Valu
return reflect.Value{}, fmt.Errorf("不支持将 %T 类型转换为 %s", value, targetType)
}
// GetParameterInfo 获取操作的参数信息
func (h *PluginHelper) GetParameterInfo(action string) (map[string]interface{}, error) {
action = strings.ToLower(action)
method, exists := h.methods[action]
if !exists {
return nil, fmt.Errorf("未知的操作: %s", action)
}
paramTypes := h.methodParams[action]
returnTypes := h.methodRetValues[action]
result := map[string]interface{}{
"name": action,
"description": fmt.Sprintf("%s 操作", method.Name),
"parameters": make(map[string]interface{}),
"returns": make(map[string]interface{}),
}
// 处理参数信息
paramsInfo := make(map[string]interface{})
// 首先检查是否有context参数
hasContext := false
if len(paramTypes) > 0 && paramTypes[0].String() == "context.Context" {
hasContext = true
result["hasContext"] = true
paramTypes = paramTypes[1:] // 跳过context参数
}
for i, paramType := range paramTypes {
// 如果是结构体参数,展开其字段
if paramType.Kind() == reflect.Struct {
structInfo := getStructInfo(paramType)
structInfo["position"] = i + 1 // 考虑到接收者和可能的context
if hasContext {
structInfo["position"] = i + 2
}
paramsInfo[paramType.Name()] = structInfo
} else {
// 基本类型参数
paramName := fmt.Sprintf("arg%d", i)
typeInfo := getTypeInfo(paramType)
typeInfo["position"] = i + 1 // 考虑到接收者
if hasContext {
typeInfo["position"] = i + 2
}
paramsInfo[paramName] = typeInfo
}
}
result["parameters"] = paramsInfo
// 处理返回值信息
returnsInfo := make(map[string]interface{})
for i, returnType := range returnTypes {
returnName := fmt.Sprintf("return%d", i)
if i == len(returnTypes)-1 && returnType.String() == "error" {
returnName = "error"
} else if i == 0 && len(returnTypes) == 2 && returnTypes[1].String() == "error" {
returnName = "result"
}
returnsInfo[returnName] = getTypeInfo(returnType)
}
result["returns"] = returnsInfo
return result, nil
}
// getStructInfo 获取结构体类型的详细信息
func getStructInfo(t reflect.Type) map[string]interface{} {
info := map[string]interface{}{
"type": "struct",
"name": t.Name(),
"package": t.PkgPath(),
"fields": make(map[string]interface{}),
"fieldCount": t.NumField(),
}
fields := make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
// 跳过非导出字段
if field.PkgPath != "" {
continue
}
fieldName := field.Name
jsonTag := field.Tag.Get("json")
if jsonTag != "" && jsonTag != "-" {
parts := strings.Split(jsonTag, ",")
if parts[0] != "" {
fieldName = parts[0]
}
}
fieldInfo := getTypeInfo(field.Type)
fieldInfo["name"] = field.Name
fieldInfo["jsonName"] = fieldName
fieldInfo["position"] = i
fieldInfo["tags"] = string(field.Tag)
fields[fieldName] = fieldInfo
}
info["fields"] = fields
return info
}
// getTypeInfo 获取类型的基本信息
func getTypeInfo(t reflect.Type) map[string]interface{} {
info := map[string]interface{}{
"typeName": t.String(),
"kind": t.Kind().String(),
"type": typeKindToString(t.Kind()),
}
// 为不同类型添加特定信息
switch t.Kind() {
case reflect.Slice, reflect.Array:
info["elemType"] = getTypeInfo(t.Elem())
case reflect.Map:
info["keyType"] = getTypeInfo(t.Key())
info["valueType"] = getTypeInfo(t.Elem())
case reflect.Ptr:
info["elemType"] = getTypeInfo(t.Elem())
case reflect.Struct:
// 对于结构体,提供简略信息
info["structName"] = t.Name()
info["package"] = t.PkgPath()
info["fieldCount"] = t.NumField()
}
return info
}
// typeKindToString 将类型Kind转换为字符串表示
func typeKindToString(kind reflect.Kind) string {
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return "integer"
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return "unsigned integer"
case reflect.Float32, reflect.Float64:
return "float"
case reflect.Bool:
return "boolean"
case reflect.String:
return "string"
case reflect.Slice, reflect.Array:
return "array"
case reflect.Map:
return "map"
case reflect.Struct:
return "object"
case reflect.Ptr:
return "pointer"
case reflect.Interface:
return "interface"
default:
return kind.String()
}
}
// BasePluginImpl 提供插件接口的基本实现用于适配Plugin接口
// 这个结构体包装了BasePlugin以便兼容context参数
type BasePluginImpl struct {
@@ -531,6 +698,23 @@ func (p *BasePluginImpl) GetAvailableActions() []string {
return p.helper.GetAvailableActions()
}
// GetOperationInfo 获取操作的参数信息
func (p *BasePluginImpl) GetOperationInfo(operation string) (map[string]interface{}, error) {
return p.helper.GetParameterInfo(operation)
}
// GetAllOperations 获取所有操作及其参数信息
func (p *BasePluginImpl) GetAllOperations() map[string]map[string]interface{} {
operations := make(map[string]map[string]interface{})
for _, action := range p.helper.GetAvailableActions() {
info, err := p.helper.GetParameterInfo(action)
if err == nil {
operations[action] = info
}
}
return operations
}
// PluginInfo 插件信息
type PluginInfo struct {
Name string `json:"name"`
@@ -1099,3 +1283,75 @@ func (pm *PluginManager) ExecuteAllPlugins(ctx context.Context, action string, p
return results
}
// GetPluginOperationInfo 获取插件特定操作的参数信息
func (pm *PluginManager) GetPluginOperationInfo(name string, operation string) (map[string]interface{}, error) {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugin, exists := pm.plugins[name]
if !exists {
return nil, fmt.Errorf("插件 %s 不存在", name)
}
if !plugin.IsEnabled() {
return nil, fmt.Errorf("插件 %s 已禁用", name)
}
return plugin.GetOperationInfo(operation)
}
// GetPluginAllOperations 获取插件所有操作及其参数信息
func (pm *PluginManager) GetPluginAllOperations(name string) (map[string]map[string]interface{}, error) {
pm.mu.RLock()
defer pm.mu.RUnlock()
plugin, exists := pm.plugins[name]
if !exists {
return nil, fmt.Errorf("插件 %s 不存在", name)
}
if !plugin.IsEnabled() {
return nil, fmt.Errorf("插件 %s 已禁用", name)
}
return plugin.GetAllOperations(), nil
}
// GetOperationsByType 获取指定类型插件的所有操作信息
func (pm *PluginManager) GetOperationsByType(pluginType PluginType) map[string]map[string]map[string]interface{} {
pm.mu.RLock()
defer pm.mu.RUnlock()
result := make(map[string]map[string]map[string]interface{})
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
for name, plugin := range typePlugins {
if !plugin.IsEnabled() {
continue
}
result[name] = plugin.GetAllOperations()
}
}
return result
}
// GetAllPluginsOperations 获取所有插件的所有操作信息
func (pm *PluginManager) GetAllPluginsOperations() map[string]map[string]map[string]interface{} {
pm.mu.RLock()
defer pm.mu.RUnlock()
result := make(map[string]map[string]map[string]interface{})
for name, plugin := range pm.plugins {
if !plugin.IsEnabled() {
continue
}
result[name] = plugin.GetAllOperations()
}
return result
}