- Introduced recordMessageMetadata and getMessageMetadata methods to manage metadata for sent messages, enabling BlockID and ThreadID inheritance in delta operations. - Implemented new methods (Append, Merge, Set) in the context to enhance message management capabilities, allowing for more flexible message updates. - Updated the Send method to automatically manage BlockID and ThreadID for delta operations, improving message handling consistency. - Enhanced JSAPI documentation to reflect new methods and usage patterns, improving developer experience and clarity.
115 lines
3.3 KiB
Go
115 lines
3.3 KiB
Go
package context
|
|
|
|
import (
|
|
"github.com/yaoapp/yao/agent/output"
|
|
"github.com/yaoapp/yao/agent/output/message"
|
|
)
|
|
|
|
// Send sends a message via the output module
|
|
// Automatically manages BlockID, ThreadID, and metadata for delta operations
|
|
// - For delta operations: inherits BlockID and ThreadID from original message
|
|
// - For new messages: auto-generates BlockID if not specified, sets ThreadID from Stack
|
|
// - Records metadata for all sent messages to enable delta inheritance
|
|
func (ctx *Context) Send(msg *message.Message) error {
|
|
output, err := ctx.getOutput()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// === Delta operations: Auto-inherit BlockID and ThreadID ===
|
|
if msg.Delta && msg.MessageID != "" {
|
|
if metadata := ctx.getMessageMetadata(msg.MessageID); metadata != nil {
|
|
// Inherit BlockID if not specified
|
|
if msg.BlockID == "" {
|
|
msg.BlockID = metadata.BlockID
|
|
}
|
|
// Inherit ThreadID if not specified
|
|
if msg.ThreadID == "" {
|
|
msg.ThreadID = metadata.ThreadID
|
|
}
|
|
}
|
|
}
|
|
|
|
// === Non-delta operations: Auto-set fields ===
|
|
if !msg.Delta {
|
|
// Auto-set ThreadID for non-root Stack (nested agent calls)
|
|
if msg.ThreadID == "" && ctx.Stack != nil && !ctx.Stack.IsRoot() {
|
|
msg.ThreadID = ctx.Stack.ID
|
|
}
|
|
|
|
// BlockID is NOT auto-generated by default (only manually specified in special cases)
|
|
// Example: Send a web card after LLM output, group them in the same Block
|
|
// Developers can specify via ctx.Send(message, blockId) or message.block_id
|
|
}
|
|
|
|
// === Record metadata for subsequent delta operations ===
|
|
ctx.recordMessageMetadata(msg)
|
|
|
|
// === Actually send the message ===
|
|
return output.Send(msg)
|
|
}
|
|
|
|
// SendGroup sends a group of messages via the output module
|
|
// Deprecated: This method is deprecated and will be removed in future versions
|
|
func (ctx *Context) SendGroup(group *message.Group) error {
|
|
output, err := ctx.getOutput()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return output.SendGroup(group)
|
|
}
|
|
|
|
// Flush flushes the output writer
|
|
func (ctx *Context) Flush() error {
|
|
output, err := ctx.getOutput()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return output.Flush()
|
|
}
|
|
|
|
// CloseOutput closes the output writer
|
|
func (ctx *Context) CloseOutput() error {
|
|
output, err := ctx.getOutput()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return output.Close()
|
|
}
|
|
|
|
// getOutput gets the output writer for the context
|
|
func (ctx *Context) getOutput() (*output.Output, error) {
|
|
if ctx.output != nil {
|
|
return ctx.output, nil
|
|
}
|
|
|
|
trace, _ := ctx.Trace()
|
|
var options message.Options = message.Options{
|
|
BaseURL: "/",
|
|
Writer: ctx.Writer,
|
|
Trace: trace,
|
|
Locale: ctx.Locale,
|
|
Accept: string(ctx.Accept),
|
|
}
|
|
|
|
// Convert ModelCapabilities to message.ModelCapabilities
|
|
if ctx.Capabilities != nil {
|
|
options.Capabilities = &message.ModelCapabilities{
|
|
Vision: ctx.Capabilities.Vision,
|
|
ToolCalls: ctx.Capabilities.ToolCalls,
|
|
Audio: ctx.Capabilities.Audio,
|
|
Reasoning: ctx.Capabilities.Reasoning,
|
|
Streaming: ctx.Capabilities.Streaming,
|
|
JSON: ctx.Capabilities.JSON,
|
|
Multimodal: ctx.Capabilities.Multimodal,
|
|
TemperatureAdjustable: ctx.Capabilities.TemperatureAdjustable,
|
|
}
|
|
}
|
|
|
|
var err error
|
|
ctx.output, err = output.NewOutput(options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ctx.output, nil
|
|
}
|