[add] Neo enter command mode by typing the /name

This commit is contained in:
Max 2023-05-12 13:20:09 +08:00
parent 46ad1e761c
commit 4bb5fca430
7 changed files with 87 additions and 15 deletions

View file

@ -2,6 +2,8 @@ package command
import ( import (
"fmt" "fmt"
"regexp"
"strings"
"github.com/yaoapp/gou/connector" "github.com/yaoapp/gou/connector"
"github.com/yaoapp/yao/aigc" "github.com/yaoapp/yao/aigc"
@ -12,6 +14,8 @@ import (
// DefaultStore the default store driver // DefaultStore the default store driver
var DefaultStore Store var DefaultStore Store
var recmd, _ = regexp.Compile(`^\/([a-zA-Z]+) +`)
var reCmdOnly, _ = regexp.Compile(`^\/([a-zA-Z]+)$`)
// SetStore the driver interface // SetStore the driver interface
func SetStore(store Store) { func SetStore(store Store) {
@ -31,6 +35,21 @@ func Match(sid string, query query.Param, input string) (string, error) {
return cid, nil return cid, nil
} }
// Match the command use the command ID
match := reCmdOnly.FindSubmatch([]byte(strings.TrimSpace(input)))
if match == nil {
match = recmd.FindSubmatch([]byte(strings.TrimSpace(input)))
}
if match != nil {
key := fmt.Sprintf("[Index]%s", match[1])
fmt.Println("Match Index:", key)
if cmd, ok := DefaultStore.Get(key); ok {
fmt.Println("Match Command:", cmd.ID)
return cmd.ID, nil
}
}
return DefaultStore.Match(query, input) return DefaultStore.Match(query, input)
} }
@ -60,13 +79,24 @@ func (cmd *Command) save() error {
}) })
} }
return DefaultStore.Set(cmd.ID, driver.Command{ data := driver.Command{
ID: cmd.ID, ID: cmd.ID,
Use: cmd.Use,
Description: cmd.Description, Description: cmd.Description,
Args: args, Args: args,
Stack: cmd.Stack, Stack: cmd.Stack,
Path: cmd.Path, Path: cmd.Path,
}) }
if cmd.Use != "" {
key := fmt.Sprintf("[Index]%s", cmd.Use)
err := DefaultStore.Set(key, data)
if err != nil {
return err
}
}
return DefaultStore.Set(cmd.ID, data)
} }
// NewAI create a new AI // NewAI create a new AI

View file

@ -60,6 +60,7 @@ func (driver *Memory) Match(query query.Param, content string) (string, error) {
has = true has = true
bytes, err := jsoniter.Marshal(map[string]interface{}{ bytes, err := jsoniter.Marshal(map[string]interface{}{
"id": cmd.ID, "id": cmd.ID,
"use": cmd.Use,
"name": cmd.Name, "name": cmd.Name,
"description": cmd.Description, "description": cmd.Description,
"args": cmd.Args, "args": cmd.Args,
@ -118,19 +119,19 @@ func (driver *Memory) Match(query query.Param, content string) (string, error) {
} }
// Set Set the command data // Set Set the command data
func (driver *Memory) Set(id string, cmd Command) error { func (driver *Memory) Set(key string, cmd Command) error {
commands.Store(id, cmd) commands.Store(key, cmd)
return nil return nil
} }
// Del delete the command data // Del delete the command data
func (driver *Memory) Del(id string) { func (driver *Memory) Del(key string) {
commands.Delete(id) commands.Delete(key)
} }
// Get the command data // Get the command data
func (driver *Memory) Get(id string) (Command, bool) { func (driver *Memory) Get(key string) (Command, bool) {
v, ok := commands.Load(id) v, ok := commands.Load(key)
if !ok { if !ok {
return Command{}, false return Command{}, false
} }

View file

@ -10,6 +10,7 @@ type Request struct {
// Command the command struct // Command the command struct
type Command struct { type Command struct {
ID string `json:"-" yaml:"-"` ID string `json:"-" yaml:"-"`
Use string `json:"use,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
Args []map[string]interface{} `json:"args,omitempty"` Args []map[string]interface{} `json:"args,omitempty"`

View file

@ -10,6 +10,8 @@ import (
v8 "github.com/yaoapp/gou/runtime/v8" v8 "github.com/yaoapp/gou/runtime/v8"
"github.com/yaoapp/kun/log" "github.com/yaoapp/kun/log"
"github.com/yaoapp/kun/maps" "github.com/yaoapp/kun/maps"
"github.com/yaoapp/kun/utils"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/neo/conversation" "github.com/yaoapp/yao/neo/conversation"
"github.com/yaoapp/yao/neo/message" "github.com/yaoapp/yao/neo/message"
"rogchap.com/v8go" "rogchap.com/v8go"
@ -18,18 +20,46 @@ import (
// Run the command // Run the command
func (req *Request) Run(messages []map[string]interface{}, cb func(msg *message.JSON) int) error { func (req *Request) Run(messages []map[string]interface{}, cb func(msg *message.JSON) int) error {
// Enter the command mode
if input, ok := messages[len(messages)-1]["content"].(string); ok {
match := reCmdOnly.FindSubmatch([]byte(strings.TrimSpace(input)))
if match != nil {
fmt.Printf("Match Command: %s | %s\n", match[1], input)
cb(req.msg().Text("Enter the command Mode"))
cb(req.msg().Done())
return nil
}
}
if config.Conf.Mode == "development" {
utils.Dump("----Request Run ----")
fmt.Printf("Command Request: %s %s\n", req.Command.ID, req.sid)
fmt.Printf("Command Process: %s\n", req.Command.Process)
fmt.Printf("Command Prepare Before: %s\n", req.Command.Prepare.Before)
fmt.Printf("Command Prepare Before: %s\n", req.Command.Prepare.After)
}
input, err := req.prepare(messages, cb) input, err := req.prepare(messages, cb)
if err != nil { if err != nil {
req.error(err, cb) req.error(err, cb)
return err return err
} }
if config.Conf.Mode == "development" {
utils.Dump("----Input After Prepare ----", input)
}
args, err := req.parseArgs(input, cb) args, err := req.parseArgs(input, cb)
if err != nil { if err != nil {
cb(req.msg().Text("\n\n" + err.Error()))
cb(req.msg().Done()) cb(req.msg().Done())
return nil return nil
} }
if config.Conf.Mode == "development" {
utils.Dump("---- Command Args ----", args)
}
// Send the command to the service // Send the command to the service
if req.Command.Optional.Confirm != "" { if req.Command.Optional.Confirm != "" {
req.confirm(args, cb) req.confirm(args, cb)
@ -167,6 +197,10 @@ func (req *Request) parseArgs(input interface{}, cb func(msg *message.JSON) int)
// RunPrepare the command // RunPrepare the command
func (req *Request) prepare(messages []map[string]interface{}, cb func(msg *message.JSON) int) (interface{}, error) { func (req *Request) prepare(messages []map[string]interface{}, cb func(msg *message.JSON) int) (interface{}, error) {
if config.Conf.Mode == "development" {
utils.Dump("----Messages Before Prepare ----", messages)
}
// Before hook // Before hook
data, err := req.prepareBefore(messages, cb) data, err := req.prepareBefore(messages, cb)
if err != nil { if err != nil {
@ -198,6 +232,10 @@ func (req *Request) prepare(messages []map[string]interface{}, cb func(msg *mess
return nil, err return nil, err
} }
if config.Conf.Mode == "development" {
utils.Dump("----Command Prompts ----", chatMessages)
}
// chat with AI // chat with AI
content := []byte{} content := []byte{}
_, ex := req.AI.ChatCompletionsWith(req.ctx, chatMessages, req.Prepare.Option, func(data []byte) int { _, ex := req.AI.ChatCompletionsWith(req.ctx, chatMessages, req.Prepare.Option, func(data []byte) int {
@ -281,7 +319,7 @@ func (req *Request) saveHistory(content []byte, messages []map[string]interface{
func (req *Request) error(err error, cb func(msg *message.JSON) int) { func (req *Request) error(err error, cb func(msg *message.JSON) int) {
cb(req.msg().Text(err.Error())) cb(req.msg().Text(err.Error()))
cb(message.New().Done()) cb(message.New().Done())
req.Done() // req.Done()
} }
func (req *Request) question(messages []map[string]interface{}) (string, error) { func (req *Request) question(messages []map[string]interface{}) (string, error) {

View file

@ -23,6 +23,7 @@ type Request struct {
type Command struct { type Command struct {
ID string `json:"-" yaml:"-"` ID string `json:"-" yaml:"-"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Use string `json:"use,omitempty"`
Connector string `json:"connector"` Connector string `json:"connector"`
Process string `json:"process"` Process string `json:"process"`
Prepare Prepare `json:"prepare"` Prepare Prepare `json:"prepare"`
@ -77,9 +78,9 @@ type Context struct {
// Store the command driver // Store the command driver
type Store interface { type Store interface {
Match(query query.Param, content string) (string, error) Match(query query.Param, content string) (string, error)
Set(id string, cmd driver.Command) error Set(key string, cmd driver.Command) error
Get(id string) (driver.Command, bool) Get(key string) (driver.Command, bool)
Del(id string) Del(key string)
SetRequest(sid, id, cid string) error SetRequest(sid, id, cid string) error
GetRequest(sid string) (string, string, bool) GetRequest(sid string) (string, string, bool)
DelRequest(sid string) DelRequest(sid string)

View file

@ -251,9 +251,9 @@ func (neo *DSL) matchCommand(ctx command.Context, messages []map[string]interfac
return nil, false return nil, false
} }
name, err := command.Match(ctx.Sid, query.Param{Stack: ctx.Stack, Path: ctx.Path}, input) id, err := command.Match(ctx.Sid, query.Param{Stack: ctx.Stack, Path: ctx.Path}, input)
if err == nil && name != "" { if err == nil && id != "" {
cmd, isCommand := command.Commands[name] cmd, isCommand := command.Commands[id]
return cmd, isCommand return cmd, isCommand
} }

View file

@ -11,6 +11,7 @@ import (
type DSL struct { type DSL struct {
ID string `json:"-" yaml:"-"` ID string `json:"-" yaml:"-"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Use string `json:"use,omitempty"`
Guard string `json:"guard,omitempty"` Guard string `json:"guard,omitempty"`
Connector string `json:"connector"` Connector string `json:"connector"`
ConversationSetting conversation.Setting `json:"conversation" yaml:"conversation"` ConversationSetting conversation.Setting `json:"conversation" yaml:"conversation"`