Merge pull request #871 from trheyi/main
Refactor assistant initialization and script context methods
This commit is contained in:
commit
53f1579806
3 changed files with 295 additions and 181 deletions
|
|
@ -68,7 +68,7 @@ func (ast *Assistant) execute(c *gin.Context, ctx chatctx.Context, input []chatM
|
||||||
ctx.Version = ast.vision
|
ctx.Version = ast.vision
|
||||||
|
|
||||||
// Run init hook
|
// Run init hook
|
||||||
res, err := ast.HookInit(c, ctx, input, options, contents)
|
res, err := ast.HookCreate(c, ctx, input, options, contents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
chatMessage.New().
|
chatMessage.New().
|
||||||
Assistant(ast.ID, ast.Name, ast.Avatar).
|
Assistant(ast.ID, ast.Name, ast.Avatar).
|
||||||
|
|
|
||||||
|
|
@ -7,24 +7,19 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/process"
|
|
||||||
"github.com/yaoapp/gou/runtime/v8/bridge"
|
|
||||||
"github.com/yaoapp/kun/log"
|
"github.com/yaoapp/kun/log"
|
||||||
chatctx "github.com/yaoapp/yao/neo/context"
|
chatctx "github.com/yaoapp/yao/neo/context"
|
||||||
"github.com/yaoapp/yao/neo/message"
|
"github.com/yaoapp/yao/neo/message"
|
||||||
chatMessage "github.com/yaoapp/yao/neo/message"
|
chatMessage "github.com/yaoapp/yao/neo/message"
|
||||||
"rogchap.com/v8go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// HookInit initialize the assistant
|
// HookCreate create a new assistant
|
||||||
func (ast *Assistant) HookInit(c *gin.Context, context chatctx.Context, input []chatMessage.Message, options map[string]interface{}, contents *chatMessage.Contents) (*ResHookInit, error) {
|
func (ast *Assistant) HookCreate(c *gin.Context, context chatctx.Context, input []chatMessage.Message, options map[string]interface{}, contents *chatMessage.Contents) (*ResHookInit, error) {
|
||||||
// Create timeout context
|
// Create timeout context
|
||||||
ctx := ast.createBackgroundContext()
|
ctx := ast.createBackgroundContext()
|
||||||
v, err := ast.call(ctx, "Init", c, contents, context, input, options)
|
v, err := ast.call(ctx, "Create", c, contents, context, input, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == HookErrorMethodNotFound {
|
if err.Error() == HookErrorMethodNotFound {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -310,9 +305,8 @@ func (ast *Assistant) call(ctx context.Context, method string, c *gin.Context, c
|
||||||
}
|
}
|
||||||
defer scriptCtx.Close()
|
defer scriptCtx.Close()
|
||||||
|
|
||||||
// Add sendMessage function to the script context
|
// Initialize the object, add the global variables, methods to the script context
|
||||||
scriptCtx.WithFunction("SendMessage", sendMessage(c, contents))
|
ast.InitObject(scriptCtx, c, context, contents)
|
||||||
scriptCtx.WithFunction("Run", ast.run(c, context, contents))
|
|
||||||
|
|
||||||
// Check if the method exists
|
// Check if the method exists
|
||||||
if !scriptCtx.Global().Has(method) {
|
if !scriptCtx.Global().Has(method) {
|
||||||
|
|
@ -320,177 +314,8 @@ func (ast *Assistant) call(ctx context.Context, method string, c *gin.Context, c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the method directly in the current thread
|
// Call the method directly in the current thread
|
||||||
args = append([]interface{}{context.Map()}, args...)
|
|
||||||
if scriptCtx != nil {
|
if scriptCtx != nil {
|
||||||
return scriptCtx.CallWith(ctx, method, args...)
|
return scriptCtx.CallWith(ctx, method, args...)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the assistant
|
|
||||||
func (ast *Assistant) run(c *gin.Context, context chatctx.Context, contents *chatMessage.Contents) func(info *v8go.FunctionCallbackInfo) *v8go.Value {
|
|
||||||
return func(info *v8go.FunctionCallbackInfo) *v8go.Value {
|
|
||||||
|
|
||||||
// Get the args
|
|
||||||
args := info.Args()
|
|
||||||
if len(args) < 2 {
|
|
||||||
return bridge.JsException(info.Context(), "Run requires at least two arguments")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the assistant id
|
|
||||||
assistantID := args[0].String()
|
|
||||||
|
|
||||||
// Get the assistant
|
|
||||||
assistant, err := Get(assistantID)
|
|
||||||
if err != nil {
|
|
||||||
return bridge.JsException(info.Context(), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// input []chatMessage.Message
|
|
||||||
var cb func(msg *chatMessage.Message)
|
|
||||||
input := args[1].String()
|
|
||||||
if len(args) > 2 {
|
|
||||||
|
|
||||||
goValue, err := bridge.GoValue(args[2], info.Context())
|
|
||||||
if err != nil {
|
|
||||||
return bridge.JsException(info.Context(), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
name := ""
|
|
||||||
userArgs := []interface{}{}
|
|
||||||
switch v := goValue.(type) {
|
|
||||||
case string:
|
|
||||||
name = v
|
|
||||||
case map[string]interface{}:
|
|
||||||
if fname, ok := v["name"].(string); ok {
|
|
||||||
name = fname
|
|
||||||
}
|
|
||||||
if args, ok := v["args"].([]interface{}); ok {
|
|
||||||
userArgs = args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(name, ".") {
|
|
||||||
cb = func(msg *chatMessage.Message) {
|
|
||||||
cbArgs := []interface{}{}
|
|
||||||
cbArgs = append(cbArgs, msg)
|
|
||||||
cbArgs = append(cbArgs, userArgs...)
|
|
||||||
p, err := process.Of(name, cbArgs...)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Failed to get the process: %s", err.Error())
|
|
||||||
color.Red("Failed to get the process: %s", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = p.Execute()
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Failed to execute the process: %s", err.Error())
|
|
||||||
color.Red("Failed to execute the process: %s", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer p.Release()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call self method
|
|
||||||
cb = func(msg *chatMessage.Message) {
|
|
||||||
cbArgs := []interface{}{}
|
|
||||||
cbArgs = append(cbArgs, msg)
|
|
||||||
cbArgs = append(cbArgs, userArgs...)
|
|
||||||
ctx, err := ast.Script.NewContext(context.Sid, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer ctx.Close()
|
|
||||||
ctx.WithFunction("SendMessage", sendMessage(c, contents))
|
|
||||||
_, err = ctx.CallWith(context, name, cbArgs...)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Failed to call the method: %s", err.Error())
|
|
||||||
color.Red("Failed to call the method: %s", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
options := map[string]interface{}{}
|
|
||||||
if len(args) > 3 {
|
|
||||||
optionsRaw, err := bridge.GoValue(args[3], info.Context())
|
|
||||||
if err != nil {
|
|
||||||
return bridge.JsException(info.Context(), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the options
|
|
||||||
if optionsRaw != nil {
|
|
||||||
switch v := optionsRaw.(type) {
|
|
||||||
case string:
|
|
||||||
err := jsoniter.UnmarshalFromString(v, &options)
|
|
||||||
if err != nil {
|
|
||||||
return bridge.JsException(info.Context(), err.Error())
|
|
||||||
}
|
|
||||||
case map[string]interface{}:
|
|
||||||
options = v
|
|
||||||
default:
|
|
||||||
return bridge.JsException(info.Context(), "Invalid options")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the assistant
|
|
||||||
context.AssistantID = assistantID
|
|
||||||
context.ChatID = fmt.Sprintf("chat_%s", uuid.New().String()) // New chat id
|
|
||||||
context.Silent = true // Silent mode
|
|
||||||
err = assistant.Execute(c, context, input, options, cb) // Execute the assistant
|
|
||||||
if err != nil {
|
|
||||||
return bridge.JsException(info.Context(), err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendMessage(c *gin.Context, contents *chatMessage.Contents) func(info *v8go.FunctionCallbackInfo) *v8go.Value {
|
|
||||||
return func(info *v8go.FunctionCallbackInfo) *v8go.Value {
|
|
||||||
|
|
||||||
// Get the message
|
|
||||||
args := info.Args()
|
|
||||||
if len(args) < 1 {
|
|
||||||
return bridge.JsException(info.Context(), "SendMessage requires at least one argument")
|
|
||||||
}
|
|
||||||
|
|
||||||
input, err := bridge.GoValue(args[0], info.Context())
|
|
||||||
if err != nil {
|
|
||||||
return bridge.JsException(info.Context(), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save history by default
|
|
||||||
saveHistory := true
|
|
||||||
if len(args) > 1 && args[1].IsBoolean() {
|
|
||||||
saveHistory = args[1].Boolean()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v := input.(type) {
|
|
||||||
case string:
|
|
||||||
// Check if the message is json
|
|
||||||
msg, err := message.NewString(v)
|
|
||||||
if err != nil {
|
|
||||||
return bridge.JsException(info.Context(), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the message to the contents
|
|
||||||
if saveHistory {
|
|
||||||
msg.AppendTo(contents)
|
|
||||||
}
|
|
||||||
msg.Write(c.Writer)
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case map[string]interface{}:
|
|
||||||
msg := message.New().Map(v)
|
|
||||||
if saveHistory {
|
|
||||||
msg.AppendTo(contents)
|
|
||||||
}
|
|
||||||
msg.Write(c.Writer)
|
|
||||||
return nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
return bridge.JsException(info.Context(), "SendMessage requires a string or a map")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
289
neo/assistant/object.go
Normal file
289
neo/assistant/object.go
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
package assistant
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"github.com/yaoapp/gou/process"
|
||||||
|
v8 "github.com/yaoapp/gou/runtime/v8"
|
||||||
|
"github.com/yaoapp/gou/runtime/v8/bridge"
|
||||||
|
"github.com/yaoapp/kun/log"
|
||||||
|
chatctx "github.com/yaoapp/yao/neo/context"
|
||||||
|
"github.com/yaoapp/yao/neo/message"
|
||||||
|
chatMessage "github.com/yaoapp/yao/neo/message"
|
||||||
|
"rogchap.com/v8go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GlobalVariables is the global variables for the assistant
|
||||||
|
type GlobalVariables struct {
|
||||||
|
Assistant *Assistant
|
||||||
|
Contents *chatMessage.Contents
|
||||||
|
Context *gin.Context
|
||||||
|
ChatContext chatctx.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// JsValue return the javascript value of the global variables
|
||||||
|
func (global *GlobalVariables) JsValue(ctx *v8go.Context) (*v8go.Value, error) {
|
||||||
|
return v8go.NewExternal(ctx.Isolate(), global)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitObject add the global variables and methods to the script context
|
||||||
|
func (ast *Assistant) InitObject(v8ctx *v8.Context, c *gin.Context, context chatctx.Context, contents *chatMessage.Contents) {
|
||||||
|
|
||||||
|
// Add global variables to the script context
|
||||||
|
v8ctx.WithGlobal("__yao_agent_global", &GlobalVariables{
|
||||||
|
Assistant: ast,
|
||||||
|
Contents: contents,
|
||||||
|
Context: c,
|
||||||
|
ChatContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add assistant to the script context
|
||||||
|
v8ctx.WithGlobal("assistant", ast.Map())
|
||||||
|
v8ctx.WithGlobal("context", context.Map())
|
||||||
|
|
||||||
|
// Add methods to the script contexts
|
||||||
|
v8ctx.WithFunction("Send", jsSend)
|
||||||
|
v8ctx.WithFunction("Call", jsCall)
|
||||||
|
}
|
||||||
|
|
||||||
|
// jsSend function, send a message to the http stream connection
|
||||||
|
func jsSend(info *v8go.FunctionCallbackInfo) *v8go.Value {
|
||||||
|
|
||||||
|
// Get the message
|
||||||
|
args := info.Args()
|
||||||
|
if len(args) < 1 {
|
||||||
|
return bridge.JsException(info.Context(), "SendMessage requires at least one argument")
|
||||||
|
}
|
||||||
|
|
||||||
|
input, err := bridge.GoValue(args[0], info.Context())
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
global, err := global(info)
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save history by default
|
||||||
|
saveHistory := true
|
||||||
|
if len(args) > 1 && args[1].IsBoolean() {
|
||||||
|
saveHistory = args[1].Boolean()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := input.(type) {
|
||||||
|
case string:
|
||||||
|
// Check if the message is json
|
||||||
|
msg, err := message.NewString(v)
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the message to the contents
|
||||||
|
if saveHistory {
|
||||||
|
msg.AppendTo(global.Contents)
|
||||||
|
}
|
||||||
|
msg.Write(global.Context.Writer)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case map[string]interface{}:
|
||||||
|
msg := message.New().Map(v)
|
||||||
|
if saveHistory {
|
||||||
|
msg.AppendTo(global.Contents)
|
||||||
|
}
|
||||||
|
msg.Write(global.Context.Writer)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return bridge.JsException(info.Context(), "Send requires a string or a map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsCall(info *v8go.FunctionCallbackInfo) *v8go.Value {
|
||||||
|
|
||||||
|
// Get the args
|
||||||
|
args := info.Args()
|
||||||
|
if len(args) < 2 {
|
||||||
|
return bridge.JsException(info.Context(), "Run requires at least two arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the assistant id
|
||||||
|
assistantID := args[0].String()
|
||||||
|
|
||||||
|
// Get the assistant
|
||||||
|
newAst, err := Get(assistantID)
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the input
|
||||||
|
input := args[1].String()
|
||||||
|
|
||||||
|
// Get the global variables
|
||||||
|
global, err := global(info)
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Context
|
||||||
|
chatContext := global.ChatContext
|
||||||
|
chatContext.AssistantID = assistantID
|
||||||
|
chatContext.ChatID = fmt.Sprintf("chat_%s", uuid.New().String()) // New chat id
|
||||||
|
chatContext.Silent = true // Silent mode
|
||||||
|
|
||||||
|
var cb func(msg *chatMessage.Message)
|
||||||
|
if len(args) > 2 {
|
||||||
|
|
||||||
|
// Parse the callback
|
||||||
|
funcType := "method"
|
||||||
|
name := ""
|
||||||
|
userArgs := []interface{}{}
|
||||||
|
if args[2].IsFunction() {
|
||||||
|
funcType = "anonymous"
|
||||||
|
} else {
|
||||||
|
goValue, err := bridge.GoValue(args[2], info.Context())
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
switch v := goValue.(type) {
|
||||||
|
case string:
|
||||||
|
name = v
|
||||||
|
case map[string]interface{}:
|
||||||
|
if fname, ok := v["name"].(string); ok {
|
||||||
|
name = fname
|
||||||
|
}
|
||||||
|
if args, ok := v["args"].([]interface{}); ok {
|
||||||
|
userArgs = args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(name, ".") {
|
||||||
|
funcType = "process"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch funcType {
|
||||||
|
case "anonymous":
|
||||||
|
source := args[2].String()
|
||||||
|
cb = func(msg *chatMessage.Message) {
|
||||||
|
cbArgs := []interface{}{msg}
|
||||||
|
ctx, err := global.Assistant.Script.NewContext(global.ChatContext.Sid, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Failed to create context", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer ctx.Close()
|
||||||
|
|
||||||
|
global.Assistant.InitObject(ctx, global.Context, chatContext, global.Contents)
|
||||||
|
_, err = ctx.CallAnonymousWith(context.Background(), source, cbArgs...)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to call the method: %s", err.Error())
|
||||||
|
color.Red("Failed to call the method: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
case "process":
|
||||||
|
|
||||||
|
cb = func(msg *chatMessage.Message) {
|
||||||
|
cbArgs := []interface{}{}
|
||||||
|
cbArgs = append(cbArgs, msg)
|
||||||
|
cbArgs = append(cbArgs, userArgs...)
|
||||||
|
p, err := process.Of(name, cbArgs...)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to get the process: %s", err.Error())
|
||||||
|
color.Red("Failed to get the process: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = p.Execute()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to execute the process: %s", err.Error())
|
||||||
|
color.Red("Failed to execute the process: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer p.Release()
|
||||||
|
}
|
||||||
|
|
||||||
|
case "method":
|
||||||
|
|
||||||
|
cb = func(msg *chatMessage.Message) {
|
||||||
|
cbArgs := []interface{}{}
|
||||||
|
cbArgs = append(cbArgs, msg)
|
||||||
|
cbArgs = append(cbArgs, userArgs...)
|
||||||
|
ctx, err := global.Assistant.Script.NewContext(global.ChatContext.Sid, nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer ctx.Close()
|
||||||
|
|
||||||
|
global.Assistant.InitObject(ctx, global.Context, global.ChatContext, global.Contents)
|
||||||
|
_, err = ctx.CallWith(context.Background(), name, cbArgs...)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to call the method: %s", err.Error())
|
||||||
|
color.Red("Failed to call the method: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the options
|
||||||
|
options := map[string]interface{}{}
|
||||||
|
if len(args) > 3 {
|
||||||
|
optionsRaw, err := bridge.GoValue(args[3], info.Context())
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the options
|
||||||
|
if optionsRaw != nil {
|
||||||
|
switch v := optionsRaw.(type) {
|
||||||
|
case string:
|
||||||
|
err := jsoniter.UnmarshalFromString(v, &options)
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
case map[string]interface{}:
|
||||||
|
options = v
|
||||||
|
default:
|
||||||
|
return bridge.JsException(info.Context(), "Invalid options")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = newAst.Execute(global.Context, chatContext, input, options, cb) // Execute the assistant
|
||||||
|
if err != nil {
|
||||||
|
return bridge.JsException(info.Context(), err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// global get the global variables
|
||||||
|
func global(info *v8go.FunctionCallbackInfo) (global *GlobalVariables, err error) {
|
||||||
|
|
||||||
|
jsGlobal, err := info.This().Get("__yao_agent_global")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to go interface
|
||||||
|
goGlobal, err := bridge.GoValue(jsGlobal, info.Context())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
global, ok := goGlobal.(*GlobalVariables)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("global is not a valid GlobalVariables")
|
||||||
|
}
|
||||||
|
|
||||||
|
return global, nil
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue