Files
smartmate/backend/newAgent/node/execute/context.go
LoveLosita 0b0ed3c61a Version: 0.9.47.dev.260427
后端:
1. execute 节点继续拆职责——超大 execute.go 下沉为 node/execute 子包,按决策流、动作路由、上下文锚点、工具执行、状态快照、工具展示与参数解析拆分;顶层 execute.go 收敛为桥接导出,降低单文件编排/业务/模型/工具逻辑混写
2. 节点公共能力继续沉到 shared——抽出 LLM 纠错回灌、完整上下文调试日志、thinking 开关、统一上下文压缩、可见 assistant 文本持久化等 node_* 公共件,减少 execute 独占实现并为其他节点复用铺路
3. speak 文本整理能力独立收口——新增 speak_text 辅助文件,补齐正文归一化的独立承载,继续收缩 execute 主文件体积

前端:
4. NewAgent 时间线接入 business_card 业务卡片协议——schedule_agent.ts 新增 task_query / task_record 卡片载荷类型与 business_card kind;AssistantPanel 增加业务卡片事件存储、时间线恢复、块渲染分支与 BusinessCardRenderer 接入,同时保留 interrupt / status / tool / reasoning 多块并存
5. 新增任务查询卡片与任务记录卡片组件,并补充 DesignDemo 设计预览页与路由,前端可先行验证 business_card 的视觉与交互落点

文档:
6. 新增 newagent business card 前后端对接说明,明确 timeline kind、payload 结构、卡片分类、前后端发射/渲染约束
2026-04-27 17:35:55 +08:00

158 lines
4.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package newagentexecute
import (
"fmt"
"strings"
"time"
newagentmodel "github.com/LoveLosita/smartflow/backend/newAgent/model"
newagentstream "github.com/LoveLosita/smartflow/backend/newAgent/stream"
"github.com/cloudwego/eino/schema"
)
const (
planCurrentStepKey = "current_step"
planCurrentStepTitle = "当前步骤"
)
func prepareExecuteNodeInput(input ExecuteNodeInput) (*newagentmodel.AgentRuntimeState, *newagentmodel.ConversationContext, *newagentstream.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 = newagentmodel.NewConversationContext("")
}
if input.ChunkEmitter == nil {
input.ChunkEmitter = newagentstream.NewChunkEmitter(newagentstream.NoopPayloadEmitter(), "", "", time.Now().Unix())
}
return input.RuntimeState, input.ConversationContext, input.ChunkEmitter, nil
}
func syncExecutePinnedContext(
conversationContext *newagentmodel.ConversationContext,
flowState *newagentmodel.CommonState,
) {
if conversationContext == nil || flowState == nil {
return
}
execContent := buildExecuteContextPinnedMarkdown(flowState)
if strings.TrimSpace(execContent) != "" {
conversationContext.UpsertPinnedBlock(newagentmodel.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(newagentmodel.ContextBlock{
Key: planCurrentStepKey,
Title: title,
Content: buildCurrentPlanStepPinnedMarkdown(step, current, total),
})
}
func appendExecuteStepAdvancedMarker(conversationContext *newagentmodel.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 *newagentmodel.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 newagentmodel.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)
}