fix(web): address model retry review feedback

This commit is contained in:
Yichen Jiang
2026-07-29 14:23:03 +08:00
parent 602f594c4b
commit 49131c47c5
28 changed files with 301 additions and 61 deletions

View File

@@ -1,6 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
README.md: 9e7dee8d5572baad13d7598d1fbde7b042dd5ab4
README.zh.md: da14d5265c16acb4e75d21bc445ef9702c83e697
# pnpm run verify-translation-pairing --write packages/client/ui-trajectory/README.md
README.md: fa8dee1b40c661f46a8e9962bd4606267b030a23
README.zh.md: 0e4c6071d7cff04d2f1b40945332d9b66ca2da1b

View File

@@ -2,7 +2,7 @@
English | [中文](README.zh.md)
Trajectory turn-list chrome (sticky Turn / Message·Step groups / step cells) plus Waterfall placeholder; the pure-consumer minimal plugin exemplar (registers two view tabs into the conversation's `'conversation.view'` slot ring, provides no service, declares no Context merge). Contract: api-contracts v3 §8.
Trajectory turn-list chrome (sticky Turn / Message·Step groups / step cells) plus Waterfall placeholder; the pure-consumer minimal plugin exemplar (registers two view tabs into the conversation's `'conversation.view'` slot ring, provides no service, declares no Context merge). Conversation nodes carrying a turn, including model-retry notices without assistant output, anchor their own trajectory span instead of inheriting the preceding turn. Contract: api-contracts v3 §8.
## Model Experience

View File

@@ -2,7 +2,7 @@
[English](README.md) | 中文
轨迹轮次列表 chrome(吸顶 Turn/Message·Step 分组/步骤单元格)及 Waterfall 占位符;这是纯消费方最小插件范例(向会话的 `'conversation.view'` slot 环注册两个视图标签页,不提供服务,也不声明 Context 合并)。契约:api-contracts v3 §8。
轨迹轮次列表 chrome(吸顶 Turn/Message·Step 分组/步骤单元格)及 Waterfall 占位符;这是纯消费方最小插件范例(向会话的 `'conversation.view'` slot 环注册两个视图标签页,不提供服务,也不声明 Context 合并)。携带轮次的会话节点(包括没有 assistant 输出的模型重试提示)会锚定自身的轨迹区段,而不会继承前一个轮次。契约:api-contracts v3 §8。
## 模型体验

View File

@@ -43,8 +43,9 @@ export interface SpanStats {
/**
* Fold snapshot nodes into per-turn spans. Only assistant nodes carry a turn
* number; user/steering/context/tool nodes attach to the turn last seen in
* sequence order (turn 0 collects the pre-assistant prologue).
* number; retry and steering nodes also carry their owning turn, while
* user/context/tool nodes attach to the turn last seen in sequence order
* (turn 0 collects the pre-assistant prologue).
* @param nodes - snapshot nodes in surface order.
* @returns spans ordered by first appearance.
*/
@@ -85,7 +86,7 @@ export function deriveSpanStats(spans: readonly TurnSpan[]): SpanStats {
}
function hasTurn(node: ConversationNode): node is ConversationNode & { turn: number } {
return node.kind === 'assistant' || node.kind === 'steering'
return node.kind === 'assistant' || node.kind === 'steering' || node.kind === 'model-retry'
}
/**

View File

@@ -208,18 +208,21 @@ describe('tab switching in ConversationRoot', () => {
})
describe('span derivation', () => {
it('attributes prologue to turn 0 and follows steering turn tags', () => {
it('attributes prologue to turn 0 and follows steering and retry turn tags', () => {
const nodes = [
{ kind: 'user', seq: 1 },
{ kind: 'steering', seq: 2, turn: 5 },
{ kind: 'user', seq: 3 },
{ kind: 'model-retry', seq: 4, turn: 6 },
{ kind: 'user', seq: 5 },
] as unknown as ConversationSnapshot['nodes']
const spans = deriveSpans(nodes)
expect(spans).toEqual([
{ turn: 0, steps: 0, calls: 0, nodes: 1 },
{ turn: 5, steps: 0, calls: 0, nodes: 2 },
{ turn: 6, steps: 0, calls: 0, nodes: 2 },
])
expect(deriveSpanStats(spans)).toEqual({ turns: 2, steps: 0, calls: 0 })
expect(deriveSpanStats(spans)).toEqual({ turns: 3, steps: 0, calls: 0 })
})
it('empty inputs produce zero stats and standalone components render their empty forms', () => {