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 结构、卡片分类、前后端发射/渲染约束
This commit is contained in:
LoveLosita
2026-04-27 17:35:55 +08:00
parent 736ba0cff3
commit 0b0ed3c61a
23 changed files with 4528 additions and 2966 deletions

View File

@@ -0,0 +1,157 @@
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)
}