- Updated the Assistant methods to include a new Contents parameter in HookInit, HookStream, HookDone, and HookFail, improving message context management. - Refactored handleChatStream to utilize the new Contents structure, enhancing the clarity and efficiency of chat interactions. - Introduced new methods in the Contents struct for better type management and properties handling, streamlining message processing. - Updated the Message struct to support new content types and properties, improving the overall message structure and serialization. These changes enhance the maintainability and robustness of the Neo API assistant, paving the way for improved message handling and assistant functionalities.
209 lines
4.7 KiB
Go
209 lines
4.7 KiB
Go
package message
|
|
|
|
import (
|
|
jsoniter "github.com/json-iterator/go"
|
|
)
|
|
|
|
const (
|
|
// ContentStatusPending the content status pending
|
|
ContentStatusPending = iota
|
|
// ContentStatusDone the content status done
|
|
ContentStatusDone
|
|
// ContentStatusError the content status error
|
|
ContentStatusError
|
|
)
|
|
|
|
// Contents the contents
|
|
type Contents struct {
|
|
Current int `json:"current"` // the current content index
|
|
Data []Data `json:"data"` // the data
|
|
}
|
|
|
|
// Data the data of the content
|
|
type Data struct {
|
|
Type string `json:"type"` // text, function, error, ...
|
|
ID string `json:"id"` // the id of the content
|
|
Function string `json:"function"` // the function name
|
|
Bytes []byte `json:"bytes"` // the content bytes
|
|
Arguments []byte `json:"arguments"` // the function arguments
|
|
Props map[string]interface{} `json:"props"` // the props
|
|
}
|
|
|
|
// NewContents create a new contents
|
|
func NewContents() *Contents {
|
|
return &Contents{
|
|
Current: -1,
|
|
Data: []Data{},
|
|
}
|
|
}
|
|
|
|
// NewText create a new text data and append to the contents
|
|
func (c *Contents) NewText(bytes []byte) *Contents {
|
|
c.Data = append(c.Data, Data{
|
|
Type: "text",
|
|
Bytes: bytes,
|
|
})
|
|
c.Current++
|
|
return c
|
|
}
|
|
|
|
// NewFunction create a new function data and append to the contents
|
|
func (c *Contents) NewFunction(function string, arguments []byte) *Contents {
|
|
c.Data = append(c.Data, Data{
|
|
Type: "function",
|
|
Function: function,
|
|
Arguments: arguments,
|
|
})
|
|
c.Current++
|
|
return c
|
|
}
|
|
|
|
// NewType create a new type data and append to the contents
|
|
func (c *Contents) NewType(typ string, props map[string]interface{}) *Contents {
|
|
c.Data = append(c.Data, Data{
|
|
Type: typ,
|
|
Props: props,
|
|
})
|
|
c.Current++
|
|
return c
|
|
}
|
|
|
|
// UpdateType update the type of the current content
|
|
func (c *Contents) UpdateType(typ string, props map[string]interface{}) *Contents {
|
|
if c.Current == -1 {
|
|
c.NewType(typ, props)
|
|
return c
|
|
}
|
|
|
|
c.Data[c.Current].Type = typ
|
|
c.Data[c.Current].Props = props
|
|
return c
|
|
}
|
|
|
|
// SetFunctionID set the id of the current function content
|
|
func (c *Contents) SetFunctionID(id string) *Contents {
|
|
if c.Current == -1 {
|
|
c.NewFunction("", []byte{})
|
|
}
|
|
c.Data[c.Current].ID = id
|
|
return c
|
|
}
|
|
|
|
// NewError create a new error data and append to the contents
|
|
func (c *Contents) NewError(err []byte) *Contents {
|
|
c.Data = append(c.Data, Data{
|
|
Type: "error",
|
|
Bytes: err,
|
|
})
|
|
c.Current++
|
|
return c
|
|
}
|
|
|
|
// AppendText append the text to the current content
|
|
func (c *Contents) AppendText(bytes []byte) *Contents {
|
|
if c.Current == -1 {
|
|
c.NewText(bytes)
|
|
return c
|
|
}
|
|
c.Data[c.Current].Bytes = append(c.Data[c.Current].Bytes, bytes...)
|
|
return c
|
|
}
|
|
|
|
// AppendFunction append the function to the current content
|
|
func (c *Contents) AppendFunction(arguments []byte) *Contents {
|
|
if c.Current == -1 {
|
|
c.NewFunction("", arguments)
|
|
return c
|
|
}
|
|
c.Data[c.Current].Arguments = append(c.Data[c.Current].Arguments, arguments...)
|
|
return c
|
|
}
|
|
|
|
// AppendError append the error to the current content
|
|
func (c *Contents) AppendError(err []byte) *Contents {
|
|
if c.Current == -1 {
|
|
c.NewError(err)
|
|
return c
|
|
}
|
|
c.Data[c.Current].Bytes = append(c.Data[c.Current].Bytes, err...)
|
|
return c
|
|
}
|
|
|
|
// JSON returns the json representation
|
|
func (c *Contents) JSON() string {
|
|
raw, _ := jsoniter.MarshalToString(c.Data)
|
|
return raw
|
|
}
|
|
|
|
// Text returns the text of the current content
|
|
func (c *Contents) Text() string {
|
|
if c.Current == -1 {
|
|
return ""
|
|
}
|
|
return string(c.Data[c.Current].Bytes)
|
|
}
|
|
|
|
// Map returns the map representation
|
|
func (data *Data) Map() (map[string]interface{}, error) {
|
|
v := map[string]interface{}{"type": data.Type}
|
|
|
|
if data.ID != "" {
|
|
v["id"] = data.ID
|
|
}
|
|
|
|
if data.Bytes != nil && data.Type == "text" {
|
|
v["text"] = string(data.Bytes)
|
|
}
|
|
|
|
if data.Props != nil && data.Type != "text" {
|
|
v["props"] = data.Props
|
|
}
|
|
|
|
if data.Arguments != nil {
|
|
var vv interface{} = nil
|
|
err := jsoniter.Unmarshal(data.Arguments, &vv)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
v["arguments"] = vv
|
|
}
|
|
|
|
if data.Function != "" {
|
|
v["function"] = data.Function
|
|
}
|
|
|
|
return v, nil
|
|
}
|
|
|
|
// MarshalJSON returns the json representation
|
|
func (data *Data) MarshalJSON() ([]byte, error) {
|
|
|
|
v := map[string]interface{}{"type": data.Type}
|
|
|
|
if data.ID != "" {
|
|
v["id"] = data.ID
|
|
}
|
|
|
|
if data.Bytes != nil && data.Type == "text" {
|
|
v["text"] = string(data.Bytes)
|
|
}
|
|
|
|
if data.Props != nil && data.Type != "text" {
|
|
v["props"] = data.Props
|
|
}
|
|
|
|
if data.Arguments != nil {
|
|
var vv interface{} = nil
|
|
err := jsoniter.Unmarshal(data.Arguments, &vv)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
v["arguments"] = vv
|
|
}
|
|
|
|
if data.Function != "" {
|
|
v["function"] = data.Function
|
|
}
|
|
|
|
return jsoniter.Marshal(v)
|
|
}
|