From 522380511d71db3610b7c6907ce6040c0c90a972 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 8 May 2023 18:42:50 +0800 Subject: [PATCH] [add] Neo studio api --- engine/load.go | 16 +++++----- neo/command/driver/memory.go | 1 - neo/command/request.go | 57 +++++++++++++++++++++++++++++++++--- neo/message/json.go | 25 ++++++++++++++++ neo/message/types.go | 1 + studio/middleware.go | 18 ++++++++++++ studio/router.go | 7 +++++ 7 files changed, 113 insertions(+), 12 deletions(-) diff --git a/engine/load.go b/engine/load.go index ee891290d5..c65b49a198 100644 --- a/engine/load.go +++ b/engine/load.go @@ -1,7 +1,6 @@ package engine import ( - "encoding/json" "fmt" "os" "strings" @@ -285,23 +284,26 @@ func loadApp(root string) error { application.Load(app) } - var info []byte - + var appData []byte + var appFile string // Read app setting if has, _ := application.App.Exists("app.yao"); has { - info, err = application.App.Read("app.yao") + appFile = "app.yao" + appData, err = application.App.Read("app.yao") if err != nil { return err } } else if has, _ := application.App.Exists("app.jsonc"); has { - info, err = application.App.Read("app.jsonc") + appFile = "app.jsonc" + appData, err = application.App.Read("app.jsonc") if err != nil { return err } } else if has, _ := application.App.Exists("app.json"); has { - info, err = application.App.Read("app.json") + appFile = "app.json" + appData, err = application.App.Read("app.json") if err != nil { return err } @@ -310,7 +312,7 @@ func loadApp(root string) error { } share.App = share.AppInfo{} - return json.Unmarshal(info, &share.App) + return application.Parse(appFile, appData, &share.App) } func printErr(mode, widget string, err error) { diff --git a/neo/command/driver/memory.go b/neo/command/driver/memory.go index 17f0e01cde..fc251ade78 100644 --- a/neo/command/driver/memory.go +++ b/neo/command/driver/memory.go @@ -92,7 +92,6 @@ func (driver *Memory) Match(query query.Param, content string) (string, error) { "content": content, }) - prompts = append([]aigc.Prompt{}, driver.prompts...) res, ex := driver.ai.ChatCompletions(messages, nil, nil) if ex != nil { return "", fmt.Errorf(ex.Message) diff --git a/neo/command/request.go b/neo/command/request.go index 1c52009402..aa721fd50c 100644 --- a/neo/command/request.go +++ b/neo/command/request.go @@ -6,10 +6,10 @@ import ( "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/kun/log" "github.com/yaoapp/kun/maps" - "github.com/yaoapp/kun/utils" "github.com/yaoapp/yao/neo/conversation" "github.com/yaoapp/yao/neo/message" "rogchap.com/v8go" @@ -30,16 +30,57 @@ func (req *Request) Run(messages []map[string]interface{}, cb func(msg *message. return nil } + // Send the command to the service if req.Command.Optional.Confirm != "" { req.confirm(args, cb) return nil } - utils.Dump(args) + // Execute the command by script + if strings.HasPrefix(req.Command.Process, "scripts.") || strings.HasPrefix(req.Command.Process, "studio.") { + + res, err := req.runScript(req.Command.Process, args, cb) + if err != nil { + cb(req.msg().Text("\n\n" + err.Error())) + return err + } + + msg := req.msg().Bind(res) + if req.Actions != nil && len(req.Actions) > 0 { + for _, action := range req.Actions { + msg.Action(action.Name, action.Type, action.Payload, action.Next) + } + } + + cb(msg.Done()) + return nil + } + + // Other process + p, err := process.Of(req.Command.Process, args...) + if err != nil { + return err + } + + res, err := p.Exec() + if err != nil { + cb(req.msg().Text("\n\n" + err.Error())) + return err + } + + msg := req.msg() + if data, ok := res.(map[string]interface{}); ok { + msg = msg.Bind(data) + } + + if req.Actions != nil && len(req.Actions) > 0 { + for _, action := range req.Actions { + msg.Action(action.Name, action.Type, action.Payload, action.Next) + } + } // DONE cb(req.msg().Done()) - return nil } @@ -280,7 +321,15 @@ func (req *Request) runScript(id string, args []interface{}, cb func(msg *messag namer := strings.Split(id, ".") method := namer[len(namer)-1] scriptID := strings.Join(namer[1:len(namer)-1], ".") - script, err := v8.Select(scriptID) + + var err error + var script *v8.Script + if namer[0] == "scripts" { + script, err = v8.Select(scriptID) + } else if namer[0] == "studio" { + script, err = v8.SelectRoot(scriptID) + } + if err != nil { return nil, err } diff --git a/neo/message/json.go b/neo/message/json.go index d7dd151899..0828f8b869 100644 --- a/neo/message/json.go +++ b/neo/message/json.go @@ -5,7 +5,9 @@ import ( "strings" jsoniter "github.com/json-iterator/go" + "github.com/yaoapp/gou/helper" "github.com/yaoapp/kun/log" + "github.com/yaoapp/kun/maps" "github.com/yaoapp/yao/openai" ) @@ -61,7 +63,15 @@ func (json *JSON) String() string { // Text set the text func (json *JSON) Text(text string) *JSON { + json.Message.Text = text + if json.Message.Data != nil { + replaced := helper.Bind(text, json.Message.Data) + if replacedText, ok := replaced.(string); ok { + json.Message.Text = replacedText + } + } + return json } @@ -89,6 +99,11 @@ func (json *JSON) Command(name, id, request string) *JSON { // Action set the action func (json *JSON) Action(name string, t string, payload interface{}, next string) *JSON { + + if json.Message.Data != nil { + payload = helper.Bind(payload, json.Message.Data) + } + json.Message.Actions = append(json.Message.Actions, Action{ Name: name, Type: t, @@ -98,6 +113,16 @@ func (json *JSON) Action(name string, t string, payload interface{}, next string return json } +// Bind replace with data +func (json *JSON) Bind(data map[string]interface{}) *JSON { + if data == nil { + return json + } + + json.Message.Data = maps.Of(data).Dot() + return json +} + // IsDone check if the message is done func (json *JSON) IsDone() bool { return json.Message.Done diff --git a/neo/message/types.go b/neo/message/types.go index cd8323ecec..a06ecb4789 100644 --- a/neo/message/types.go +++ b/neo/message/types.go @@ -7,6 +7,7 @@ type Message struct { Confirm bool `json:"confirm,omitempty"` Command *Command `json:"command,omitempty"` Actions []Action `json:"actions,omitempty"` + Data map[string]interface{} } // Action the action diff --git a/studio/middleware.go b/studio/middleware.go index 65ec31189d..f0f59151d1 100644 --- a/studio/middleware.go +++ b/studio/middleware.go @@ -63,6 +63,24 @@ func hdCORS(c *gin.Context) { func hdAuth(c *gin.Context) { tokenString := c.Request.Header.Get("Authorization") + + // Get token from query + if tokenString == "" { + + // Temporary solution (will be removed in the future) + tokenString = strings.TrimSpace(strings.TrimPrefix(c.Query("token"), "Bearer ")) + if tokenString == "" { + c.JSON(403, gin.H{"code": 403, "message": "No permission"}) + c.Abort() + return + } + + claims := helper.JwtValidate(tokenString, []byte(config.Conf.JWTSecret)) + c.Set("__sid", claims.SID) + c.Next() + return + } + if strings.HasPrefix(tokenString, "Bearer") { tokenString = strings.TrimSpace(strings.TrimPrefix(tokenString, "Bearer ")) if tokenString == "" { diff --git a/studio/router.go b/studio/router.go index b0dc126bb8..b54b700e83 100644 --- a/studio/router.go +++ b/studio/router.go @@ -11,6 +11,7 @@ import ( "github.com/gin-gonic/gin" jsoniter "github.com/json-iterator/go" v8 "github.com/yaoapp/gou/runtime/v8" + "github.com/yaoapp/yao/neo" ) var regExcp = regexp.MustCompile("^Exception\\|([0-9]+):(.+)$") @@ -236,6 +237,12 @@ func setRouter(router *gin.Engine) { c.JSON(200, res) c.Done() }) + + // Neo API for studio + if neo.Neo != nil { + neo.Neo.API(router, "/neo") + } + } func throw(c *gin.Context, code int, message string) {