Add shared space methods to JavaScript bridge

- Implement Set, Get, Del, and Clear methods for shared space interactions
- Add error handling and validation for shared space method calls
- Enhance context management with Release method to clear shared space
- Update context initialization to create a default memory shared space
This commit is contained in:
Max 2025-02-27 16:32:25 +08:00
parent ae599d9b83
commit ca6d075a22
3 changed files with 154 additions and 3 deletions

View file

@ -230,6 +230,7 @@ func (neo *DSL) handleChat(c *gin.Context) {
// Set the context with validated chat_id
ctx, cancel := chatctx.NewWithCancel(sid, chatID, c.Query("context"))
defer cancel()
defer ctx.Release() // Release the context after the request is done
neo.Answer(ctx, content, c)
}

View file

@ -52,6 +52,145 @@ func (ast *Assistant) InitObject(v8ctx *v8.Context, c *gin.Context, context chat
v8ctx.WithFunction("Send", jsSend)
v8ctx.WithFunction("Call", jsCall)
v8ctx.WithFunction("Assets", jsAssets)
// Shared space methods
v8ctx.WithFunction("Set", jsSet)
v8ctx.WithFunction("Get", jsGet)
v8ctx.WithFunction("Del", jsDel)
v8ctx.WithFunction("Clear", jsClear)
}
// jsSet function, set a value to the shared space
func jsSet(info *v8go.FunctionCallbackInfo) *v8go.Value {
global, err := global(info)
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
if global.ChatContext.SharedSpace == nil {
return bridge.JsException(info.Context(), "Shared space is not set")
}
args := info.Args()
if len(args) < 2 {
return bridge.JsException(info.Context(), "Set requires at least two arguments")
}
if !args[0].IsString() {
return bridge.JsException(info.Context(), "Set requires a valid key")
}
// Validate the key
key := args[0].String()
if key == "" {
return bridge.JsException(info.Context(), "Set requires a valid key")
}
// Validate the value
value, err := bridge.GoValue(args[1], info.Context())
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
// Set the value
err = global.ChatContext.SharedSpace.Set(key, value)
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
return nil
}
// jsGet function, get a value from the shared space
func jsGet(info *v8go.FunctionCallbackInfo) *v8go.Value {
global, err := global(info)
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
if global.ChatContext.SharedSpace == nil {
return bridge.JsException(info.Context(), "Shared space is not set")
}
args := info.Args()
if len(args) < 1 {
return bridge.JsException(info.Context(), "Get requires at least one argument")
}
if !args[0].IsString() {
return bridge.JsException(info.Context(), "Get requires a valid key")
}
// Get the key
key := args[0].String()
if key == "" {
return bridge.JsException(info.Context(), "Get requires a valid key")
}
// Get the value
value, err := global.ChatContext.SharedSpace.Get(key)
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
jsValue, err := bridge.JsValue(info.Context(), value)
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
return jsValue
}
// jsDel function, delete a value from the shared space
func jsDel(info *v8go.FunctionCallbackInfo) *v8go.Value {
global, err := global(info)
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
if global.ChatContext.SharedSpace == nil {
return bridge.JsException(info.Context(), "Shared space is not set")
}
args := info.Args()
if len(args) < 1 {
return bridge.JsException(info.Context(), "Get requires at least one argument")
}
if !args[0].IsString() {
return bridge.JsException(info.Context(), "Get requires a valid key")
}
// Get the key
key := args[0].String()
if key == "" {
return bridge.JsException(info.Context(), "Get requires a valid key")
}
err = global.ChatContext.SharedSpace.Delete(key)
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
return nil
}
func jsClear(info *v8go.FunctionCallbackInfo) *v8go.Value {
global, err := global(info)
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
if global.ChatContext.SharedSpace == nil {
return bridge.JsException(info.Context(), "Shared space is not set")
}
err = global.ChatContext.SharedSpace.Clear()
if err != nil {
return bridge.JsException(info.Context(), err.Error())
}
return nil
}
// jsAssets function, get the assets content

View file

@ -5,6 +5,7 @@ import (
"time"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/plan"
"github.com/yaoapp/kun/log"
)
@ -14,8 +15,8 @@ type Context struct {
Sid string `json:"sid" yaml:"-"` // Session ID
ChatID string `json:"chat_id,omitempty"` // Chat ID, use to select chat
AssistantID string `json:"assistant_id,omitempty"` // Assistant ID, use to select assistant
Stack string `json:"stack,omitempty"`
Path string `json:"pathname,omitempty"`
Stack string `json:"stack,omitempty"` // will be removed in the future
Path string `json:"pathname,omitempty"` // wiil be rename to path
FormData map[string]interface{} `json:"formdata,omitempty"`
Field *Field `json:"field,omitempty"`
Namespace string `json:"namespace,omitempty"`
@ -26,6 +27,7 @@ type Context struct {
Upload *FileUpload `json:"upload,omitempty"`
Version bool `json:"version,omitempty"` // Version support
RAG bool `json:"rag,omitempty"` // RAG support
SharedSpace plan.Space `json:"-"` // Shared space
}
// Field the context field
@ -47,7 +49,8 @@ type FileUpload struct {
// New create a new context
func New(sid, cid, payload string) Context {
ctx := Context{Context: context.Background(), Sid: sid, ChatID: cid}
ctx := Context{Context: context.Background(), Sid: sid, ChatID: cid, SharedSpace: plan.NewMemorySharedSpace()}
if payload == "" {
return ctx
}
@ -56,6 +59,7 @@ func New(sid, cid, payload string) Context {
if err != nil {
log.Error("%s", err.Error())
}
return ctx
}
@ -85,6 +89,13 @@ func WithTimeout(parent Context, timeout time.Duration) (Context, context.Cancel
return parent, cancel
}
// Release the context
func (ctx *Context) Release() {
ctx.SharedSpace.Clear()
ctx.SharedSpace = nil
ctx = nil
}
// Map the context to a map
func (ctx *Context) Map() map[string]interface{} {
data := map[string]interface{}{