Fix orchestrator logic and workspace push for planning confirmation and artifact handling
This commit is contained in:
@@ -381,9 +381,10 @@ func (o *Orchestrator) buildUnifiedSystemPrompt(userInput string, recentMessages
|
||||
if planningMode {
|
||||
planningModeDoc = strings.Join([]string{
|
||||
"当前处于 PI 规划编辑模式。",
|
||||
"- 用户的修订意见必须基于现有 Artifact 继续迭代。",
|
||||
"- 需要继续调用 safe_pi_planning / publish_pi_plan 相关流程生成更新版本。",
|
||||
"- 不要仅给普通文本答复替代蓝图更新。",
|
||||
"- 如果用户表达了确认意图(如 确认、开始创建工单、批量创建、没问题 等),你必须立即调用 create_gitea_ticket 工具,将 PI 蓝图中的 Feature 和 Enabler 逐一拆解为 User Story 并创建工单。严禁重复输出蓝图或再次征求确认。",
|
||||
"- 如果用户提出了修改意见,则基于现有 Artifact 继续迭代,调用 publish_pi_plan 生成更新版本。",
|
||||
"- 不要仅给普通文本答复替代蓝图更新或工单创建。必须通过工具调用来执行实际操作。",
|
||||
"- 不要在文本中虚构工具调用结果。如果需要创建工单,必须实际调用 create_gitea_ticket 工具。",
|
||||
}, "\n")
|
||||
}
|
||||
|
||||
@@ -905,38 +906,40 @@ func (o *Orchestrator) runUnifiedReActStream(ctx context.Context, chatID, userID
|
||||
if finalText == "" {
|
||||
finalText = "已完成处理。"
|
||||
}
|
||||
if planningMode && !workspaceSentThisTurn {
|
||||
// 提取 artifact 标签内的文档内容作为工作区内容
|
||||
if planningMode && !workspaceSentThisTurn && !isPlanningConfirmation(userInput) {
|
||||
// 仅当 LLM 输出包含 <artifact> 标签时,才提取其内容推送到工作区分屏
|
||||
// 如果不包含 artifact 标签,说明是 LLM 推理中间步骤,不推送到工作区
|
||||
workspaceContent := extractArtifactContent(finalText)
|
||||
if workspaceContent == "" {
|
||||
workspaceContent = stripArtifactTags(finalText)
|
||||
}
|
||||
if workspaceContent == "" {
|
||||
workspaceContent = finalText
|
||||
}
|
||||
o.activatePlanningSession(chatID, userID, workspaceContent, true)
|
||||
if err := o.store.SaveMessage(chatID, userID, "assistant", wrapPIArtifact(workspaceContent)); err != nil {
|
||||
if o.log != nil {
|
||||
o.log.Warnf("%s save planning artifact failed chat_id=%s err=%v", traceLogPrefix, chatID, err)
|
||||
if workspaceContent != "" {
|
||||
o.activatePlanningSession(chatID, userID, workspaceContent, true)
|
||||
if err := o.store.SaveMessage(chatID, userID, "assistant", wrapPIArtifact(workspaceContent)); err != nil {
|
||||
if o.log != nil {
|
||||
o.log.Warnf("%s save planning artifact failed chat_id=%s err=%v", traceLogPrefix, chatID, err)
|
||||
}
|
||||
}
|
||||
if err := callback(StreamEvent{
|
||||
Type: StreamEventTypeWorkspaceStart,
|
||||
WorkspaceTitle: "PI Planning Document",
|
||||
}); err != nil {
|
||||
return "", fmt.Errorf("callback error: %w", err)
|
||||
}
|
||||
if err := callback(StreamEvent{
|
||||
Type: StreamEventTypeWorkspaceDelta,
|
||||
Content: workspaceContent,
|
||||
}); err != nil {
|
||||
return "", fmt.Errorf("callback error: %w", err)
|
||||
}
|
||||
if err := callback(StreamEvent{Type: StreamEventTypeWorkspaceEnd}); err != nil {
|
||||
return "", fmt.Errorf("callback error: %w", err)
|
||||
}
|
||||
workspaceSentThisTurn = true
|
||||
finalText = stripArtifactTags(finalText)
|
||||
if finalText == "" {
|
||||
finalText = "PI 规划已生成,请查看右侧工作区。如确认无误,请回复确认进入工单创建。"
|
||||
}
|
||||
} else if o.log != nil {
|
||||
o.log.Infof("%s planning mode final answer has no artifact tags, skip workspace push", traceLogPrefix)
|
||||
}
|
||||
if err := callback(StreamEvent{
|
||||
Type: StreamEventTypeWorkspaceStart,
|
||||
WorkspaceTitle: "PI Planning Document",
|
||||
}); err != nil {
|
||||
return "", fmt.Errorf("callback error: %w", err)
|
||||
}
|
||||
if err := callback(StreamEvent{
|
||||
Type: StreamEventTypeWorkspaceDelta,
|
||||
Content: workspaceContent,
|
||||
}); err != nil {
|
||||
return "", fmt.Errorf("callback error: %w", err)
|
||||
}
|
||||
if err := callback(StreamEvent{Type: StreamEventTypeWorkspaceEnd}); err != nil {
|
||||
return "", fmt.Errorf("callback error: %w", err)
|
||||
}
|
||||
workspaceSentThisTurn = true
|
||||
finalText = "我已根据你的意见更新 PI 规划,请查看右侧工作区;如确认无误,请回复“确认”进入工单创建。"
|
||||
} else if planningMode {
|
||||
// 工作区已在本轮通过工具调用发送,剥离 final 内容中的 artifact 标签
|
||||
finalText = stripArtifactTags(finalText)
|
||||
@@ -1441,7 +1444,9 @@ func isPlanningConfirmation(userInput string) bool {
|
||||
}
|
||||
markers := []string{
|
||||
"确认", "同意", "可以创建", "开始创建", "继续创建", "执行下一步", "没问题,继续",
|
||||
"confirm", "approved", "go ahead", "proceed",
|
||||
"创建工单", "批量创建", "下发工单", "同步到gitea", "同步到 gitea",
|
||||
"没问题", "可以了", "没有问题", "没有异议", "无异议",
|
||||
"confirm", "approved", "go ahead", "proceed", "create ticket", "create issue",
|
||||
}
|
||||
for _, marker := range markers {
|
||||
if strings.Contains(text, marker) {
|
||||
|
||||
Reference in New Issue
Block a user