Merge master and address submission echo review

This commit is contained in:
creatixchu
2026-08-26 13:20:24 +08:00
318 changed files with 11158 additions and 5019 deletions
@@ -237,19 +237,8 @@ export class FakeApiClient implements IApiClient {
readonly agentPresets: IApiClient['agentPresets'] = {
list: (payload: unknown) => this.record('agentPreset.list', payload, Promise.resolve(ok({ presets: [], authorable: false, hasDocument: false }))),
select: (payload: { agentPreset: string }) =>
this.record('agentPreset.select', payload, Promise.resolve(ok({ agentPreset: payload.agentPreset }))),
read: (payload: { agentPreset: string }) =>
this.record('agentPreset.read', payload, Promise.resolve(ok({
agentPreset: payload.agentPreset, trust: 'user' as const, content: '',
}))),
copy: (payload: { agentPreset: string }) =>
this.record('agentPreset.copy', payload, Promise.resolve(ok({ agentPreset: payload.agentPreset }))),
openDocument: (payload: { agentPreset: string }) =>
this.record('agentPreset.openDocument', payload, Promise.resolve(ok({ opened: true as const }))),
remove: (payload: { agentPreset: string }) =>
this.record('agentPreset.remove', payload, Promise.resolve(ok({}))),
}
readonly skills: IApiClient['skills'] = {
@@ -191,6 +191,27 @@ describe('observed retirement', () => {
expect(retirements).toEqual([{ reason: 'observed', attachments: [] }])
})
it('retires once when the queue and durable event report the same request id', async () => {
const { api, session } = makeSession()
api.onHistory = () => Promise.resolve(ok(historyValue([])))
await session.open()
const retirements: PendingSubmissionRetirement[] = []
const handle = session.beginSubmission({
text: '同一请求',
images: [],
onRetire: retirement => retirements.push(retirement),
})
session.handleControlFrame({
type: 'queue', sessionId: SID, items: [queuedItem(handle.requestId, [])],
})
await api.pushFollow(SID, {
type: 'event', event: promptEvent(0, handle.requestId) as never,
})
await settleFrames()
expect(retirements).toEqual([{ reason: 'observed', attachments: [] }])
expect(session.getSnapshot().pendingSubmissions).toEqual([])
})
it('uses requestAnimationFrame for the retirement delay when the runtime provides one', async () => {
const frames: FrameRequestCallback[] = []
vi.stubGlobal('requestAnimationFrame', (fn: FrameRequestCallback) => {