Version: 0.9.48.dev.260428

后端:
1.新增任务批量状态查询能力,补齐入参归一化、单次上限控制、按当前用户隔离与空结果兼容。
2.QuickTask 从纯文本升级为“正文 + business_card”输出,覆盖 task_record/task_query 两类卡片语义。
3.查询链路新增时间窗边界筛选与异常窗口兜底,SSE/timeline 同步扩展 business_card 事件并持久化。

前端:
1.助手面板接入任务状态 hydration 与增量同步,卡片状态可实时联动(完成/撤销、编辑、删除、同步中)。
2.TaskRecord/TaskQuery 卡片升级为可交互任务卡,并新增对话页任务编辑弹窗与回写闭环。
3.助手路由升级为 /assistant/:id?,支持 URL 驱动会话切换与刷新恢复。

仓库:
同步更新 business card 前端对接说明文档。
This commit is contained in:
Losita
2026-04-28 00:32:33 +08:00
parent 20d8f2acae
commit 495d520b20
19 changed files with 1864 additions and 212 deletions

View File

@@ -358,6 +358,18 @@ func (e *ChunkEmitter) EmitScheduleCompleted(blockID, stage string) error {
return e.emitExtraOnly(NewScheduleCompletedExtra(blockID, stage))
}
// EmitBusinessCard 输出一次业务结果卡片事件。
//
// 协议约束:
// 1. 只走 extra不附带 content/reasoning
// 2. card 为空时直接跳过,避免发出缺少关键字段的空卡片。
func (e *ChunkEmitter) EmitBusinessCard(blockID, stage string, card *StreamBusinessCardExtra) error {
if e == nil || e.emit == nil || card == nil {
return nil
}
return e.emitExtraOnly(NewBusinessCardExtra(blockID, stage, card))
}
// EmitFinish 统一输出 stop 结束块,并带上 finish extra。
func (e *ChunkEmitter) EmitFinish(blockID, stage string) error {
if e == nil || e.emit == nil {

View File

@@ -46,6 +46,7 @@ const (
StreamExtraKindToolResult StreamExtraKind = "tool_result"
StreamExtraKindConfirm StreamExtraKind = "confirm_request"
StreamExtraKindInterrupt StreamExtraKind = "interrupt"
StreamExtraKindBusinessCard StreamExtraKind = "business_card"
StreamExtraKindFinish StreamExtraKind = "finish"
StreamExtraKindScheduleCompleted StreamExtraKind = "schedule_completed"
)
@@ -63,18 +64,19 @@ const (
//
// 职责边界:
// 1. Kind / Stage / BlockID 提供前端排版和分组所需的最小元信息;
// 2. Status / Tool / Confirm / Interrupt 只存展示层真正需要的摘要,不直接耦合后端完整状态对象;
// 2. Status / Tool / Confirm / Interrupt / BusinessCard 只存展示层真正需要的摘要,不直接耦合后端完整状态对象;
// 3. Meta 留给后续做灰度扩展,避免每加一种小字段都要立刻改 DTO 结构。
type OpenAIChunkExtra struct {
Kind StreamExtraKind `json:"kind,omitempty"`
BlockID string `json:"block_id,omitempty"`
Stage string `json:"stage,omitempty"`
DisplayMode StreamDisplayMode `json:"display_mode,omitempty"`
Status *StreamStatusExtra `json:"status,omitempty"`
Tool *StreamToolExtra `json:"tool,omitempty"`
Confirm *StreamConfirmExtra `json:"confirm,omitempty"`
Interrupt *StreamInterruptExtra `json:"interrupt,omitempty"`
Meta map[string]any `json:"meta,omitempty"`
Kind StreamExtraKind `json:"kind,omitempty"`
BlockID string `json:"block_id,omitempty"`
Stage string `json:"stage,omitempty"`
DisplayMode StreamDisplayMode `json:"display_mode,omitempty"`
Status *StreamStatusExtra `json:"status,omitempty"`
Tool *StreamToolExtra `json:"tool,omitempty"`
Confirm *StreamConfirmExtra `json:"confirm,omitempty"`
Interrupt *StreamInterruptExtra `json:"interrupt,omitempty"`
BusinessCard *StreamBusinessCardExtra `json:"business_card,omitempty"`
Meta map[string]any `json:"meta,omitempty"`
}
// StreamStatusExtra 表示普通阶段状态或提示性事件。
@@ -105,6 +107,20 @@ type StreamInterruptExtra struct {
Summary string `json:"summary,omitempty"`
}
// StreamBusinessCardExtra 表示一张业务结果卡片。
//
// 职责边界:
// 1. CardType 只允许前端已约定的卡片类型task_query/task_record
// 2. Source 仅在 task_record 时有语义,其他卡片类型可为空;
// 3. Data 承载“可直接渲染的最小快照”,避免前端再二次补拉才能看到结果。
type StreamBusinessCardExtra struct {
CardType string `json:"card_type,omitempty"`
Title string `json:"title,omitempty"`
Summary string `json:"summary,omitempty"`
Source string `json:"source,omitempty"`
Data map[string]any `json:"data,omitempty"`
}
// ToOpenAIStream 把 Eino message 转成 OpenAI 兼容 chunk。
func ToOpenAIStream(chunk *schema.Message, requestID, modelName string, created int64, includeRole bool) (string, error) {
return ToOpenAIStreamWithExtra(chunk, requestID, modelName, created, includeRole, nil)
@@ -263,6 +279,17 @@ func NewInterruptExtra(blockID, stage, interactionID, interactionType, summary s
}
}
// NewBusinessCardExtra 创建“业务结果卡片”事件的 extra。
func NewBusinessCardExtra(blockID, stage string, businessCard *StreamBusinessCardExtra) *OpenAIChunkExtra {
return &OpenAIChunkExtra{
Kind: StreamExtraKindBusinessCard,
BlockID: blockID,
Stage: stage,
DisplayMode: StreamDisplayModeCard,
BusinessCard: businessCard,
}
}
// NewScheduleCompletedExtra 创建”排程完毕”卡片事件的 extra。
//
// 职责边界:
@@ -331,5 +358,6 @@ func hasStreamExtra(extra *OpenAIChunkExtra) bool {
extra.Tool != nil ||
extra.Confirm != nil ||
extra.Interrupt != nil ||
extra.BusinessCard != nil ||
len(extra.Meta) > 0
}