inbox.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import type { Inbox, InboxTarget } from '@deepseek-ai/dsh-agent'
  2. import type { MessageId } from '@deepseek-ai/dsh-llm'
  3. import type { UserMessage } from '@deepseek-ai/dsh-session'
  4. /**
  5. * Create a mutable in-memory Inbox stub for tests that exercise only the public
  6. * queue operations. Durable events, projection validation, and live Inbox
  7. * notifications require a real Agent created by the AgentLoop test harness.
  8. * @returns an Inbox backed by two process-local arrays.
  9. */
  10. export function createInboxStub(): Inbox {
  11. const pending: Record<InboxTarget, UserMessage[]> = {
  12. 'next-turn': [],
  13. 'next-step': [],
  14. }
  15. const locate = (messageId: MessageId): { target: InboxTarget; index: number } | undefined => {
  16. for (const target of ['next-turn', 'next-step'] as const) {
  17. const index = pending[target].findIndex(message => message.id === messageId)
  18. if (index >= 0) return { target, index }
  19. }
  20. return undefined
  21. }
  22. return {
  23. get nextTurn() { return pending['next-turn'] },
  24. get nextStep() { return pending['next-step'] },
  25. clear() {
  26. pending['next-step'].splice(0)
  27. pending['next-turn'].splice(0)
  28. },
  29. append(target, message) {
  30. pending[target].push(message)
  31. },
  32. prepend(target, message) {
  33. pending[target].unshift(message)
  34. },
  35. replace(messageId, message) {
  36. const location = locate(messageId)
  37. if (location === undefined) return false
  38. pending[location.target].splice(location.index, 1, message)
  39. return true
  40. },
  41. remove(messageId) {
  42. const location = locate(messageId)
  43. if (location === undefined) return false
  44. pending[location.target].splice(location.index, 1)
  45. return true
  46. },
  47. splice(target, start, deleteCount, inserted) {
  48. return pending[target].splice(start, deleteCount, ...inserted)
  49. },
  50. }
  51. }
  52. /**
  53. * Create an unsupported Inbox placeholder for Agent stubs whose tests do not exercise Inbox behavior.
  54. * @returns an Inbox whose pending lists are empty and whose mutation methods throw.
  55. */
  56. export function unsupportedInbox(): Inbox {
  57. const rejectMutation = (): never => {
  58. throw new Error('this test Agent does not support Inbox mutations')
  59. }
  60. return {
  61. nextTurn: [],
  62. nextStep: [],
  63. clear: rejectMutation,
  64. append: rejectMutation,
  65. prepend: rejectMutation,
  66. replace: rejectMutation,
  67. remove: rejectMutation,
  68. splice: rejectMutation,
  69. }
  70. }