新增: 执行中轨迹卡展开与占用期消息必达
- 执行中 step 卡支持点击展开(复用轨迹展开态, 实时过程工具卡回看) - 占用期消息改落待发箱自动续投, 不再拒绝让用户重发(959) - 待发项派发后完成结果回推来源飞书会话(35min 弃守) - 961 轮次语义/960 聚合防抖设计要点登记
This commit is contained in:
@@ -1032,7 +1032,7 @@ type RenderItem =
|
||||
// A 过程压缩:完成轮次的执行轨迹卡(traceMsgs 为折叠在内的过程消息)与执行中的实时步骤摘要;
|
||||
// round=轨迹序号(卡头「第 N 轮」,与执行中步骤行、轮次导航条同一计数来源)
|
||||
| { kind: 'trace'; key: string; round: number; stats: TurnCallStats; startTs: number; endTs: number; tokens: number; traceMsgs: AiMessage[]; expanded: boolean }
|
||||
| { kind: 'step'; key: string; round: number; stats: TurnCallStats }
|
||||
| { kind: 'step'; key: string; round: number; stats: TurnCallStats; traceMsgs: AiMessage[]; expanded: boolean }
|
||||
// UX 密度改造:相邻消息间隔 ≥30 分钟或跨天的居中时间分隔线(替代 per-block 相对时间)
|
||||
| { kind: 'timesep'; key: string; ts: number }
|
||||
// S1 子代理完成卡(AiAgentFinished 事件):非消息数据(per-conv 存 aiShared),逐卡一项
|
||||
@@ -1121,7 +1121,12 @@ function genBucketItems(
|
||||
pushSep(msgs[0].timestamp)
|
||||
// 闪烁修复(2026-10-09):step 项 key 与下方完成态 trace 项对齐(同为 trace-{首条id}),
|
||||
// 使「执行中 step → 完成态 trace」切换时 Vue 复用同一 DOM 节点(key 稳定),不销毁重建。
|
||||
items.push({ kind: 'step', key: 'trace-' + prev[0].id, round, stats: collectTurnStats(msgs) })
|
||||
// 961①: step 卡可展开——key 与完成态 trace 同构,复用 expandedTraceIds,
|
||||
// 执行中展开看实时过程,完成后切换 trace 态展开不丢
|
||||
items.push({
|
||||
kind: 'step', key: 'trace-' + prev[0].id, round, stats: collectTurnStats(msgs),
|
||||
traceMsgs: prev, expanded: expandedTraceIds.value.has('trace-' + prev[0].id),
|
||||
})
|
||||
} else {
|
||||
pushSep(cur.timestamp)
|
||||
}
|
||||
@@ -1676,12 +1681,35 @@ defineExpose({
|
||||
骨架与完成态 .ai-trace-card 完全同构(卡头结构一致),仅 chevron→脉冲点、右侧→「进行中」,
|
||||
使 step→trace 切换时只 patch 内部文字,无高度跳变/闪烁 -->
|
||||
<div v-else-if="item.kind === 'step'" class="ai-msg-slot ai-msg-slot--proc">
|
||||
<div class="ai-trace-card ai-trace-card--running">
|
||||
<div class="ai-trace-head">
|
||||
<div class="ai-trace-card ai-trace-card--running" :class="{ 'ai-trace-card--open': item.expanded }">
|
||||
<div
|
||||
class="ai-trace-head"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
:aria-expanded="item.expanded"
|
||||
@click="toggleTrace(item.key)"
|
||||
@keydown.enter.prevent="toggleTrace(item.key)"
|
||||
@keydown.space.prevent="toggleTrace(item.key)"
|
||||
>
|
||||
<span class="ai-trace-chevron" :class="{ 'is-open': item.expanded }">▸</span>
|
||||
<span class="ai-step-dot"></span>
|
||||
<span class="ai-trace-title">{{ $t('ai.trace.roundN', { n: item.round }) }}</span>
|
||||
<span class="ai-trace-agg">{{ stepText(item.stats, item.round) }}</span>
|
||||
<span class="ai-trace-toggle ai-trace-toggle--running">{{ $t('ai.trace.running') }}</span>
|
||||
<span class="ai-trace-toggle">{{ item.expanded ? $t('ai.trace.collapse') : $t('ai.trace.running') }}</span>
|
||||
</div>
|
||||
<!-- 961① 执行中展开:实时过程回看(每条过程消息的工具卡),与完成态 trace 展开同诉求 -->
|
||||
<div v-if="item.expanded" class="ai-trace-body">
|
||||
<template v-for="m in item.traceMsgs" :key="m.id">
|
||||
<div v-if="m.toolCalls && m.toolCalls.length > 0" class="ai-trace-round">
|
||||
<ToolCardList
|
||||
:toolCalls="m.toolCalls"
|
||||
@approve="({ id, approved, decision }) => store.approveToolCall(id, approved, decision)"
|
||||
@batch-approve="(decision) => store.batchApprove(decision)"
|
||||
@install-obscura="onInstallObscura"
|
||||
@pending-out-of-view="onPendingOutOfView"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user