event-script.ts 4.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { createUserMessage, createMessage, createToolResultMessage, CallId } from '@deepseek-ai/dsh-llm'
  2. // Minimal SessionEvent builders for orchestration tests (shape mirrors what the
  3. // host emits; only the fields the object layer reads).
  4. import type { ContentBlock } from '@deepseek-ai/dsh-llm/types'
  5. import type { SessionEvent } from '@deepseek-ai/dsh-session/types'
  6. /** One text content block (local helper). */
  7. const text = (t: string): ContentBlock[] => [{ type: 'text', text: t }]
  8. const at = (seq: number, e: Record<string, unknown>): SessionEvent =>
  9. ({ seq, time: 1_700_000_000_000 + seq, ...e }) as unknown as SessionEvent
  10. export const ev = {
  11. turnStart: (seq: number, turn: number): SessionEvent =>
  12. at(seq, { type: 'turn/start', data: { turn, trigger: { kind: 'message', source: { kind: 'user' } } } }),
  13. user: (seq: number, body: string): SessionEvent =>
  14. at(seq, { type: 'user/message', surfaceOp: 'append', data: createUserMessage({
  15. content: text(body), source: { kind: 'user' },
  16. }) }),
  17. stepStart: (seq: number, turn: number, step = 0): SessionEvent =>
  18. at(seq, { type: 'step/start', data: { turn, step } }),
  19. chunkStart: (seq: number, turn: number, step = 0, index = 0): SessionEvent =>
  20. at(seq, { type: 'assistant/chunk', data: { turn, step, chunk: { type: 'block-start', index, blockType: 'text' } } }),
  21. chunkText: (seq: number, turn: number, piece: string, step = 0, index = 0): SessionEvent =>
  22. at(seq, { type: 'assistant/chunk', data: { turn, step, chunk: { type: 'text-delta', index, text: piece } } }),
  23. assistant: (seq: number, turn: number, body: string, step = 0): SessionEvent =>
  24. at(seq, { type: 'assistant/message', surfaceOp: 'append', data: {
  25. turn, step,
  26. message: createMessage({
  27. role: 'assistant',
  28. content: text(body),
  29. source: {
  30. kind: 'model',
  31. ...{ provider: 'fake', model: 'fk-1' },
  32. },
  33. }),
  34. } }),
  35. toolCall: (seq: number, turn: number, callId: string, name: string, args: string, step = 0): SessionEvent =>
  36. at(seq, { type: 'tool/call', data: { turn, step, callId, name, arguments: args } }),
  37. toolResult: (seq: number, turn: number, callId: string, body: string, step = 0): SessionEvent =>
  38. at(seq, {
  39. type: 'tool/result',
  40. surfaceOp: 'append',
  41. data: {
  42. turn,
  43. step,
  44. message: createToolResultMessage({
  45. callId: CallId(callId),
  46. content: text(body),
  47. isError: false,
  48. }),
  49. },
  50. }),
  51. codeDispatchStart: (seq: number, parentCallId: string, n: number, name: string, args: unknown): SessionEvent =>
  52. at(seq, {
  53. type: 'tool/code-dispatch-start',
  54. data: { parentCallId, subCallId: `${parentCallId}:code:${n}`, name, arguments: args },
  55. }),
  56. codeDispatch: (seq: number, parentCallId: string, n: number, name: string, args: unknown, body: string, isError = false): SessionEvent =>
  57. at(seq, {
  58. type: 'tool/code-dispatch',
  59. data: { parentCallId, subCallId: `${parentCallId}:code:${n}`, name, arguments: args, isError, content: text(body) },
  60. }),
  61. stepEnd: (seq: number, turn: number, step = 0): SessionEvent =>
  62. at(seq, { type: 'step/end', data: { turn, step } }),
  63. turnEnd: (seq: number, turn: number, reason: 'completed' | 'cancelled' = 'completed'): SessionEvent =>
  64. at(seq, { type: 'turn/end', data: { turn, reason: { kind: reason } } }),
  65. commandRun: (seq: number, commandId: string, name: string, args = ''): SessionEvent =>
  66. at(seq, { type: 'command/run', data: { commandId, name, args, source: { kind: 'user' } } }),
  67. commandDone: (seq: number, commandId: string, kind: 'success' | 'error' = 'success', text?: string): SessionEvent =>
  68. at(seq, { type: 'command/done', data: { commandId, kind, ...text === undefined ? {} : { text } } }),
  69. }
  70. /** One complete plain turn (turn/start → user → step → assistant → turn/end), 6 events from startSeq. */
  71. export function plainTurn(startSeq: number, turn: number, ask: string, answer: string): SessionEvent[] {
  72. return [
  73. ev.turnStart(startSeq, turn),
  74. ev.user(startSeq + 1, ask),
  75. ev.stepStart(startSeq + 2, turn),
  76. ev.assistant(startSeq + 3, turn, answer),
  77. ev.stepEnd(startSeq + 4, turn),
  78. ev.turnEnd(startSeq + 5, turn),
  79. ]
  80. }
  81. /** Wrap raw events as view-less history entries (the wire shape history now returns). */
  82. export function entries(events: readonly SessionEvent[]): { event: SessionEvent }[] {
  83. return events.map(event => ({ event }))
  84. }