Version: 0.9.75.dev.260505
后端: 1.收口阶段 6 agent 结构迁移,将 newAgent 内核与 agentsvc 编排层迁入 services/agent - 切换 Agent 启动装配与 HTTP handler 直连 agent sv,移除旧 service agent bridge - 补齐 Agent 对 memory、task、task-class、schedule 的 RPC 适配与契约字段 - 扩展 schedule、task、task-class RPC/contract 支撑 Agent 查询、写入与 provider 切流 - 更新迁移文档、README 与相关注释,明确 agent 当前切流点和剩余 memory 迁移面
This commit is contained in:
157
backend/services/agent/node/execute/context.go
Normal file
157
backend/services/agent/node/execute/context.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package agentexecute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
agentmodel "github.com/LoveLosita/smartflow/backend/services/agent/model"
|
||||
agentstream "github.com/LoveLosita/smartflow/backend/services/agent/stream"
|
||||
"github.com/cloudwego/eino/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
planCurrentStepKey = "current_step"
|
||||
planCurrentStepTitle = "当前步骤"
|
||||
)
|
||||
|
||||
func prepareExecuteNodeInput(input ExecuteNodeInput) (*agentmodel.AgentRuntimeState, *agentmodel.ConversationContext, *agentstream.ChunkEmitter, error) {
|
||||
if input.RuntimeState == nil {
|
||||
return nil, nil, nil, fmt.Errorf("execute node: runtime state 不能为空")
|
||||
}
|
||||
if input.Client == nil {
|
||||
return nil, nil, nil, fmt.Errorf("execute node: execute client 未注入")
|
||||
}
|
||||
|
||||
input.RuntimeState.EnsureCommonState()
|
||||
if input.ConversationContext == nil {
|
||||
input.ConversationContext = agentmodel.NewConversationContext("")
|
||||
}
|
||||
if input.ChunkEmitter == nil {
|
||||
input.ChunkEmitter = agentstream.NewChunkEmitter(agentstream.NoopPayloadEmitter(), "", "", time.Now().Unix())
|
||||
}
|
||||
return input.RuntimeState, input.ConversationContext, input.ChunkEmitter, nil
|
||||
}
|
||||
|
||||
func syncExecutePinnedContext(
|
||||
conversationContext *agentmodel.ConversationContext,
|
||||
flowState *agentmodel.CommonState,
|
||||
) {
|
||||
if conversationContext == nil || flowState == nil {
|
||||
return
|
||||
}
|
||||
|
||||
execContent := buildExecuteContextPinnedMarkdown(flowState)
|
||||
if strings.TrimSpace(execContent) != "" {
|
||||
conversationContext.UpsertPinnedBlock(agentmodel.ContextBlock{
|
||||
Key: executePinnedKey,
|
||||
Title: "执行上下文",
|
||||
Content: execContent,
|
||||
})
|
||||
}
|
||||
|
||||
if !flowState.HasPlan() {
|
||||
conversationContext.RemovePinnedBlock(planCurrentStepKey)
|
||||
return
|
||||
}
|
||||
|
||||
step, ok := flowState.CurrentPlanStep()
|
||||
if !ok {
|
||||
conversationContext.RemovePinnedBlock(planCurrentStepKey)
|
||||
return
|
||||
}
|
||||
|
||||
current, total := flowState.PlanProgress()
|
||||
title := strings.TrimSpace(planCurrentStepTitle)
|
||||
if title == "" {
|
||||
title = "当前步骤"
|
||||
}
|
||||
conversationContext.UpsertPinnedBlock(agentmodel.ContextBlock{
|
||||
Key: planCurrentStepKey,
|
||||
Title: title,
|
||||
Content: buildCurrentPlanStepPinnedMarkdown(step, current, total),
|
||||
})
|
||||
}
|
||||
|
||||
func appendExecuteStepAdvancedMarker(conversationContext *agentmodel.ConversationContext) {
|
||||
if conversationContext == nil {
|
||||
return
|
||||
}
|
||||
|
||||
history := conversationContext.HistorySnapshot()
|
||||
if len(history) > 0 {
|
||||
last := history[len(history)-1]
|
||||
if last != nil && last.Extra != nil {
|
||||
if kind, ok := last.Extra[executeHistoryKindKey].(string); ok && strings.TrimSpace(kind) == executeHistoryKindStepAdvanced {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conversationContext.AppendHistory(&schema.Message{
|
||||
Role: schema.Assistant,
|
||||
Content: "",
|
||||
Extra: map[string]any{
|
||||
executeHistoryKindKey: executeHistoryKindStepAdvanced,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func buildExecuteContextPinnedMarkdown(flowState *agentmodel.CommonState) string {
|
||||
if flowState == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
lines := make([]string, 0, 8)
|
||||
if flowState.HasPlan() {
|
||||
lines = append(lines, "执行模式:计划执行(按步骤推进)")
|
||||
current, total := flowState.PlanProgress()
|
||||
lines = append(lines, fmt.Sprintf("计划进度:第 %d/%d 步", current, total))
|
||||
|
||||
if step, ok := flowState.CurrentPlanStep(); ok {
|
||||
lines = append(lines, "当前步骤:"+compactExecutePinnedText(step.Content))
|
||||
doneWhen := compactExecutePinnedText(step.DoneWhen)
|
||||
if doneWhen != "" {
|
||||
lines = append(lines, "完成判定(done_when):"+doneWhen)
|
||||
}
|
||||
lines = append(lines, "动作纪律:未满足 done_when 禁止 next_plan;满足后优先 next_plan。")
|
||||
} else {
|
||||
lines = append(lines, "当前步骤:不可读(可能已执行完成)")
|
||||
}
|
||||
} else {
|
||||
lines = append(lines, "执行模式:自由执行(无预定义步骤)")
|
||||
}
|
||||
|
||||
if flowState.MaxRounds > 0 {
|
||||
lines = append(lines, fmt.Sprintf("轮次预算:%d/%d", flowState.RoundUsed, flowState.MaxRounds))
|
||||
}
|
||||
return strings.TrimSpace(strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
func buildCurrentPlanStepPinnedMarkdown(step agentmodel.PlanStep, current, total int) string {
|
||||
lines := make([]string, 0, 4)
|
||||
lines = append(lines, fmt.Sprintf("步骤进度:第 %d/%d 步", current, total))
|
||||
|
||||
content := compactExecutePinnedText(step.Content)
|
||||
if content == "" {
|
||||
content = "(空)"
|
||||
}
|
||||
lines = append(lines, "步骤内容:"+content)
|
||||
|
||||
doneWhen := compactExecutePinnedText(step.DoneWhen)
|
||||
if doneWhen != "" {
|
||||
lines = append(lines, "完成判定:"+doneWhen)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
func compactExecutePinnedText(text string) string {
|
||||
text = strings.TrimSpace(text)
|
||||
if text == "" {
|
||||
return ""
|
||||
}
|
||||
text = strings.ReplaceAll(text, "\r\n", "\n")
|
||||
text = strings.ReplaceAll(text, "\n", ";")
|
||||
return strings.TrimSpace(text)
|
||||
}
|
||||
Reference in New Issue
Block a user