Merge final master into Web transcript
This commit is contained in:
@@ -122,6 +122,13 @@ describe('conversation slot inject surface', () => {
|
||||
const chatView = b.chatViewSurface(ROOT)
|
||||
chatView.injected.loadOlder()
|
||||
expect(b.sessionFake.loadOlder).toHaveBeenCalledTimes(1)
|
||||
chatView.injected.forkAt(17)
|
||||
await vi.waitFor(() => {
|
||||
expect(b.runtime.sessions.calls).toContainEqual({ method: 'open', args: [ROOT] })
|
||||
})
|
||||
expect(b.runtime.sessions.calls).toContainEqual({
|
||||
method: 'fork', args: [{ sessionId: ROOT, atSeq: 17, increaseTitle: true }],
|
||||
})
|
||||
await b.runtime.dispose()
|
||||
})
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ function makeHarness(init?: Partial<ConversationSnapshot>) {
|
||||
const openDetails = vi.fn<(t: SelectionTarget) => void>()
|
||||
const openFile = vi.fn<(path: string) => void>()
|
||||
const loadOlder = vi.fn()
|
||||
const forkAt = vi.fn()
|
||||
// Selection rides the REAL chat store (same construction path as
|
||||
// production; the view reads it through the PropsStore useStore share).
|
||||
// renderSlot stub renders the render-site fallback (an empty keyed ledger:
|
||||
@@ -120,9 +121,10 @@ function makeHarness(init?: Partial<ConversationSnapshot>) {
|
||||
openDetails,
|
||||
openFile,
|
||||
loadOlder,
|
||||
forkAt,
|
||||
}
|
||||
const setSelection = (next: SelectionTarget | null): void => { chat.actions.select(next) }
|
||||
return { set, ChatView, props, openDetails, openFile, loadOlder, setSelection }
|
||||
return { set, ChatView, props, openDetails, openFile, loadOlder, forkAt, setSelection }
|
||||
}
|
||||
|
||||
describe('chat-flow derivation', () => {
|
||||
@@ -194,6 +196,16 @@ describe('ChatView', () => {
|
||||
expect(view.getByText('run a')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('forks from both user and finalized assistant message actions at their event seq', () => {
|
||||
const h = makeHarness({ nodes: [user(1, 'question'), assistant(2, 'answer')] })
|
||||
const view = render(<h.ChatView {...h.props} />)
|
||||
const buttons = view.getAllByRole('button', { name: '在新对话中分支' })
|
||||
expect(buttons).toHaveLength(2)
|
||||
fireEvent.click(buttons[0]!)
|
||||
fireEvent.click(buttons[1]!)
|
||||
expect(h.forkAt.mock.calls).toEqual([[1], [2]])
|
||||
})
|
||||
|
||||
it('renders assistant Markdown across history, streaming, final, and interrupted states while user text stays literal', () => {
|
||||
const markdown = '# Rendered\n\n- **one**\n- `two`'
|
||||
const h = makeHarness({ nodes: [user(1, markdown), assistant(2, markdown)] })
|
||||
|
||||
Reference in New Issue
Block a user