protocol.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /**
  2. * Versionless, structured-clone wire protocol between co-shipped host and worker code. The host
  3. * treats inbound traffic as hostile because model code can forge `parentPort` messages; the
  4. * worker trusts host replies.
  5. * @module @deepseek-ai/dsh-code-runtime-worker/src/protocol
  6. */
  7. /** What the host hands the worker at spawn, via `workerData`. */
  8. export interface WorkerBootData {
  9. /** The type-stripped (plain JS) program body. */
  10. code: string
  11. /** Binding namespaces to materialize: the global name plus the function names (functions themselves stay host-side). */
  12. namespaces: { global: string; names: string[] }[]
  13. /** Shared byte budget for captured log text; exceeding it drops further entries after one in-band marker. */
  14. maxLogBytes: number
  15. /** Byte cap for the rendered completion value (see the value-preparation contract in bootstrap.ts). */
  16. maxValueBytes: number
  17. }
  18. /** Worker → host: one bridged binding call. */
  19. interface CallMessage {
  20. type: 'call'
  21. /** Worker-issued correlation id; the host answers each id at most once and ignores duplicates. */
  22. id: number
  23. /** The namespace global the call targets. */
  24. global: string
  25. /** The function name within the namespace. */
  26. name: string
  27. /** The single argument, structured-clone-plain. */
  28. args: unknown
  29. }
  30. /** Worker → host: captured text, streamed eagerly so output survives a mid-run termination (timeout, abort, OOM). */
  31. interface LogMessage {
  32. type: 'log'
  33. text: string
  34. }
  35. /**
  36. * Worker → host: the program settled. `error` carries a program exception
  37. * (the only failure the bootstrap itself can report — budgets, aborts, and
  38. * substrate death are observed host-side). `value` is present only on a
  39. * clean completion that produced one (already size-capped and
  40. * clone-safe per the bootstrap's value preparation). Logs are NOT carried
  41. * here — they streamed eagerly as {@link LogMessage}s.
  42. */
  43. export interface DoneMessage {
  44. type: 'done'
  45. value?: unknown
  46. error?: { message: string }
  47. }
  48. /** Every message the worker sends. */
  49. export type WorkerToHost = CallMessage | LogMessage | DoneMessage
  50. /** Host → worker: the answer to one {@link CallMessage}. */
  51. export type ReplyMessage =
  52. | { type: 'reply'; id: number; ok: true; value: unknown }
  53. | { type: 'reply'; id: number; ok: false; message: string }
  54. /**
  55. * The in-band marker entry text announcing that log capture stopped at the
  56. * byte budget. Shared wire vocabulary: the worker's LogBuffer emits it when
  57. * ITS budget exhausts, and the host emits the identical text when its own
  58. * ledger drops an entry first (forged port traffic, stray pipe bytes) — so
  59. * a truncated run reads the same however the cap was hit.
  60. * @param maxBytes - the configured `maxLogBytes` the marker names.
  61. * @returns the marker line.
  62. */
  63. export function logTruncationMarker(maxBytes: number): string {
  64. return `[dsh-code-runtime-worker] log capture truncated at ${maxBytes} bytes`
  65. }