feat: align conversation state, composer and scoped approvals
This commit is contained in:
1 parent
771ca540f7
commit
308b98df23
61 files changed
+1701
-292
No files matched your search
@@ -95,10 +95,10 @@ const activePrefixSummary = buildCompletedFoldModel([
|
||||
], { turnFinished: false })
|
||||
assert.ok(activePrefixSummary)
|
||||
assert.deepEqual(activePrefixSummary.summaryGroups.map(group => [group.startIndex, group.endIndex, group.shouldFold]), [
|
||||
[0, 1, true], [3, 4, true]
|
||||
[0, 1, true], [3, 4, false]
|
||||
])
|
||||
assert.equal(activePrefixSummary.summaryGroups[0].isRunning, true)
|
||||
assert.equal(activePrefixSummary.segments.filter(segment => segment.kind === 'unit' && segment.unit.kind === 'summary').length, 2)
|
||||
assert.equal(activePrefixSummary.summaryGroups[0].isRunning, false)
|
||||
assert.equal(activePrefixSummary.segments.filter(segment => segment.kind === 'unit' && segment.unit.kind === 'summary').length, 1)
|
||||
|
||||
const initialInspectionMarkup = renderToStaticMarkup(<MessageBubble message={{
|
||||
id: 'streaming-inspection', role: 'assistant', status: 'streaming', createdAt: 1,
|
||||
@@ -127,27 +127,11 @@ const streamingInspectionMarkup = renderToStaticMarkup(<MessageBubble message={{
|
||||
{ id: 'inspect-src', name: 'list_dir', status: 'stream_executing', args: { path: 'src' } }
|
||||
]
|
||||
}} />)
|
||||
assert.equal((initialInspectionMarkup.match(/cr-streaming-activity/g) ?? []).length, 1)
|
||||
assert.match(initialInspectionMarkup, /读取 接手状态-2026-10-15/)
|
||||
assert.equal((streamingInspectionMarkup.match(/cr-streaming-activity/g) ?? []).length, 1,
|
||||
'new tool calls replace the current activity row instead of nesting under the first action')
|
||||
assert.match(streamingInspectionMarkup, /正在查看文件列表 src/)
|
||||
assert.match(streamingInspectionMarkup, /data-activity-tool-id="inspect-src"/)
|
||||
assert.match(streamingInspectionMarkup, /已处理 1s/,
|
||||
'the elapsed duration starts at one second and is visible while the assistant turn is streaming')
|
||||
assert.match(streamingInspectionMarkup, /cr-collapse--process cr-collapse--collapsed cr-live-event-feed/,
|
||||
'the current action is an expandable event feed before the turn finishes')
|
||||
assert.match(streamingInspectionMarkup, /aria-label="展开事件消息列表"/)
|
||||
assert.match(streamingInspectionMarkup, /aria-controls="live-events-streaming-inspection-content"/)
|
||||
assert.match(streamingInspectionMarkup, /data-event-type="reasoning"[^]*data-event-type="tool"/,
|
||||
'reasoning and tool calls appear as ordered event messages')
|
||||
assert.doesNotMatch(streamingInspectionMarkup, /过程消息/)
|
||||
assert.match(streamingInspectionMarkup, /data-tool-name="list_dir"[^]*data-tool-name="read_file"/,
|
||||
'all supported live tool details are mounted inside the independently expandable process section')
|
||||
assert.doesNotMatch(streamingInspectionMarkup, /cr-collapse--summary/,
|
||||
'streaming actions have no expandable parent summary')
|
||||
assert.match(streamingInspectionMarkup, /<strong>Listing project, reading h/,
|
||||
'deep-thinking details remain available and render Markdown instead of exposing raw markers')
|
||||
assert.equal((initialInspectionMarkup.match(/cr-streaming-activity/g) ?? []).length, 0, 'unfinished tail is not a summary')
|
||||
assert.equal((streamingInspectionMarkup.match(/cr-streaming-activity/g) ?? []).length, 0)
|
||||
assert.match(streamingInspectionMarkup, /已处理 1s/)
|
||||
assert.match(streamingInspectionMarkup, /data-tool-name="list_dir"[^]*data-tool-name="read_file"/)
|
||||
assert.match(streamingInspectionMarkup, /<strong>Listing project, reading h/)
|
||||
|
||||
const completedInspectionMarkup = renderToStaticMarkup(<MessageBubble message={{
|
||||
id: 'completed-inspection', role: 'assistant', status: 'done', createdAt: 1, content: 'Done.',
|
||||
@@ -312,12 +296,8 @@ const streamingToolIntentMarkup = renderToStaticMarkup(<MessageBubble message={{
|
||||
parts: [{ type: 'tool', toolId: 'list-src' }],
|
||||
tools: [{ id: 'list-src', name: 'list_dir', status: 'running', intent: 'Inspecting source layout', args: { path: 'src' }, argsRaw: '{"path":"src"}' }]
|
||||
}} />)
|
||||
assert.match(streamingToolIntentMarkup, /正在查看文件列表 src/,
|
||||
'the one live activity row uses the localized summary for the current tool call')
|
||||
const liveIntentStatusRow = streamingToolIntentMarkup.match(/<div class="cr-captured-tool cr-streaming-activity"[^]*?<\/div><\/div>/)?.[0] ?? ''
|
||||
assert.ok(liveIntentStatusRow)
|
||||
assert.doesNotMatch(liveIntentStatusRow, /Inspecting source layout/,
|
||||
'provider English intent stays out of the operation status line')
|
||||
assert.doesNotMatch(streamingToolIntentMarkup, /cr-streaming-activity/, 'single live tool stays independent')
|
||||
assert.match(streamingToolIntentMarkup, /data-tool-name="list_dir"/)
|
||||
for (const status of ['cancelled', 'error'] as const) {
|
||||
const terminalMarkup = renderToStaticMarkup(<MessageBubble message={{
|
||||
id: `terminal-${status}`, role: 'assistant', status, createdAt: 1, turnDurationMs: 65_000,
|
||||
|
||||
Reference in new issue
Block a user