assistant-stream.host.spec.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import { describe, expect, it } from 'vitest'
  2. import { LlmAttemptId } from '@deepseek-ai/dsh-llm'
  3. import { SessionSeq } from '@deepseek-ai/dsh-session'
  4. import { SessionAssistantStreamAccumulator } from '../src/assistant-stream.ts'
  5. describe('SessionAssistantStreamAccumulator', () => {
  6. it('replaces stale lifecycles, rejects frame gaps, and caches each baseline', () => {
  7. const accumulator = new SessionAssistantStreamAccumulator()
  8. const empty = accumulator.snapshot()
  9. expect(accumulator.snapshot()).toBe(empty)
  10. accumulator.accept({
  11. type: 'start', attemptId: LlmAttemptId('stale'), revision: 2, turn: 1, step: 1,
  12. }, -1)
  13. expect(accumulator.snapshot()).toEqual({ revision: 2 })
  14. accumulator.accept({
  15. type: 'start', attemptId: LlmAttemptId('current'), revision: 1, turn: 2, step: 3,
  16. }, SessionSeq(5))
  17. expect(accumulator.snapshot()).toMatchObject({
  18. revision: 1,
  19. activeAttempt: {
  20. attemptId: 'current', startedAfterSeq: 5, turn: 2, step: 3, nextIndex: 0, stream: [],
  21. },
  22. })
  23. accumulator.accept({
  24. type: 'chunk', attemptId: LlmAttemptId('other'), revision: 2, index: 0,
  25. time: 4, chunk: { type: 'text-delta', index: 0, text: 'lost' },
  26. }, SessionSeq(5))
  27. expect(accumulator.snapshot()).toEqual({ revision: 2 })
  28. accumulator.accept({
  29. type: 'start', attemptId: LlmAttemptId('settled'), revision: 3, turn: 2, step: 4,
  30. }, SessionSeq(8))
  31. accumulator.accept({
  32. type: 'chunk', attemptId: LlmAttemptId('settled'), revision: 4, index: 0,
  33. time: 5, chunk: { type: 'text-delta', index: 0, text: 'ok' },
  34. }, SessionSeq(8))
  35. const active = accumulator.snapshot()
  36. expect(active).toMatchObject({
  37. revision: 4,
  38. activeAttempt: {
  39. attemptId: 'settled', startedAfterSeq: 8, nextIndex: 1,
  40. stream: [{ type: 'text-chunks', time0: 5, index: 0, dt: [], texts: ['ok'] }],
  41. },
  42. })
  43. expect(accumulator.snapshot()).toBe(active)
  44. accumulator.accept({
  45. type: 'end', attemptId: LlmAttemptId('settled'), revision: 5, index: 1,
  46. outcome: { kind: 'abandoned' },
  47. }, SessionSeq(9))
  48. expect(accumulator.snapshot()).toEqual({ revision: 5 })
  49. })
  50. })