protocol.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /**
  2. * The host⇄worker wire protocol: one string-valued enum of message tags per direction, a
  3. * payload map giving each tag its parameters (the single source of truth), and the message
  4. * unions derived from them. Payloads are plain JSON by construction for structured clone. Both
  5. * directions are closed engine protocols whose receivers use `assertNever`; generic typed senders
  6. * make tag/payload mismatches compile-time errors rather than silently skipped messages.
  7. * @module @deepseek-ai/dsh-workflow-workerthread/protocol
  8. */
  9. import type { WorkflowAgentEndInfo, WorkflowAgentInfo, WorkflowResult } from '@deepseek-ai/dsh-workflow'
  10. import type { ChildResult, ChildStartRequest } from './types.ts'
  11. /** Message tags the worker sends the host (the wire values are the tag strings). */
  12. export enum WorkerToHostType {
  13. /** The startup handshake: the session is listening and awaits {@link HostToWorkerType.Go}. */
  14. Ready = 'ready',
  15. /** Observer narration: a `phase(title)` call. */
  16. Phase = 'phase',
  17. /** Observer narration: a `log(message)` call. */
  18. Log = 'log',
  19. /** Observer lifecycle: one `agent()` call started a child. */
  20. AgentStart = 'agent-start',
  21. /** Observer lifecycle: one `agent()` call settled. */
  22. AgentEnd = 'agent-end',
  23. /** Child RPC: start a child on the host (answered by ChildStarted or ChildStartError). */
  24. ChildStart = 'child-start',
  25. /** Child RPC: dispose a started child (answered by ChildDisposed). */
  26. ChildDispose = 'child-dispose',
  27. /** The run's single terminal result. */
  28. Result = 'result',
  29. }
  30. /** The payload each worker→host tag carries. */
  31. export interface WorkerToHostPayloads {
  32. /** Ready carries nothing. */
  33. [WorkerToHostType.Ready]: Record<never, never>
  34. /** The phase title, verbatim. */
  35. [WorkerToHostType.Phase]: { title: string }
  36. /** The logged message, verbatim. */
  37. [WorkerToHostType.Log]: { message: string }
  38. /** The call's sequence number, label, phase, and child id. */
  39. [WorkerToHostType.AgentStart]: { info: WorkflowAgentInfo }
  40. /** The call identity plus its outcome. */
  41. [WorkerToHostType.AgentEnd]: { info: WorkflowAgentEndInfo }
  42. /** The RPC correlation id and the prompt plus validated options. */
  43. [WorkerToHostType.ChildStart]: { callId: number; request: ChildStartRequest }
  44. /** The RPC correlation id of the child to dispose. */
  45. [WorkerToHostType.ChildDispose]: { callId: number }
  46. /** The run's terminal outcome. */
  47. [WorkerToHostType.Result]: { result: WorkflowResult }
  48. }
  49. /** Message tags the host sends the worker (the wire values are the tag strings). */
  50. export enum HostToWorkerType {
  51. /** Releases the startup gate: run the script body. */
  52. Go = 'go',
  53. /** Cancel the run: hooks start throwing and the script dies at its next await. */
  54. Cancel = 'cancel',
  55. /** Child RPC reply: the provider fulfilled with a published run (exactly one start reply per ChildStart). */
  56. ChildStarted = 'child-started',
  57. /** Child RPC reply: the provider's asynchronous start failed. */
  58. ChildStartError = 'child-start-error',
  59. /** Child RPC: a started child's result RESOLVED (its JSON projection). */
  60. ChildSettled = 'child-settled',
  61. /** Child RPC: a started child's result REJECTED (an infrastructure fault, rendered). */
  62. ChildFailed = 'child-failed',
  63. /** Child RPC reply: a requested disposal completed. */
  64. ChildDisposed = 'child-disposed',
  65. }
  66. /** The payload each host→worker tag carries. */
  67. export interface HostToWorkerPayloads {
  68. /** Go carries nothing. */
  69. [HostToWorkerType.Go]: Record<never, never>
  70. /** The cancel reason, canonical for the whole run. */
  71. [HostToWorkerType.Cancel]: { reason: string }
  72. /** The RPC correlation id and the child agent's id (minted by the subagent seam). */
  73. [HostToWorkerType.ChildStarted]: { callId: number; childId: string }
  74. /** The RPC correlation id and the rendered start failure. */
  75. [HostToWorkerType.ChildStartError]: { callId: number; rendered: string }
  76. /** The RPC correlation id and the child's terminal result projection. */
  77. [HostToWorkerType.ChildSettled]: { callId: number; result: ChildResult }
  78. /** The RPC correlation id and the rendered infrastructure fault. */
  79. [HostToWorkerType.ChildFailed]: { callId: number; rendered: string }
  80. /** The RPC correlation id of the completed disposal. */
  81. [HostToWorkerType.ChildDisposed]: { callId: number }
  82. }
  83. /**
  84. * One worker→host message of tag `T`; unparameterized, the closed union over
  85. * every tag (a discriminated union — `switch` on `type` narrows).
  86. */
  87. export type WorkerToHostMessage<T extends WorkerToHostType = WorkerToHostType> =
  88. { [K in T]: { type: K } & WorkerToHostPayloads[K] }[T]
  89. /**
  90. * One host→worker message of tag `T`; unparameterized, the closed union over
  91. * every tag (a discriminated union — `switch` on `type` narrows).
  92. */
  93. export type HostToWorkerMessage<T extends HostToWorkerType = HostToWorkerType> =
  94. { [K in T]: { type: K } & HostToWorkerPayloads[K] }[T]