message.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import z from "zod"
  2. import { Bus } from "../bus"
  3. import { Provider } from "../provider/provider"
  4. import { NamedError } from "../util/error"
  5. export namespace Message {
  6. export const OutputLengthError = NamedError.create(
  7. "SessionOutputLengthError",
  8. z.object({}),
  9. )
  10. export const ToolCall = z
  11. .object({
  12. state: z.literal("call"),
  13. step: z.number().optional(),
  14. toolCallId: z.string(),
  15. toolName: z.string(),
  16. args: z.custom<Required<unknown>>(),
  17. })
  18. .openapi({
  19. ref: "Message.ToolInvocation.ToolCall",
  20. })
  21. export type ToolCall = z.infer<typeof ToolCall>
  22. export const ToolPartialCall = z
  23. .object({
  24. state: z.literal("partial-call"),
  25. step: z.number().optional(),
  26. toolCallId: z.string(),
  27. toolName: z.string(),
  28. args: z.custom<Required<unknown>>(),
  29. })
  30. .openapi({
  31. ref: "Message.ToolInvocation.ToolPartialCall",
  32. })
  33. export type ToolPartialCall = z.infer<typeof ToolPartialCall>
  34. export const ToolResult = z
  35. .object({
  36. state: z.literal("result"),
  37. step: z.number().optional(),
  38. toolCallId: z.string(),
  39. toolName: z.string(),
  40. args: z.custom<Required<unknown>>(),
  41. result: z.string(),
  42. })
  43. .openapi({
  44. ref: "Message.ToolInvocation.ToolResult",
  45. })
  46. export type ToolResult = z.infer<typeof ToolResult>
  47. export const ToolInvocation = z
  48. .discriminatedUnion("state", [ToolCall, ToolPartialCall, ToolResult])
  49. .openapi({
  50. ref: "Message.ToolInvocation",
  51. })
  52. export type ToolInvocation = z.infer<typeof ToolInvocation>
  53. export const TextPart = z
  54. .object({
  55. type: z.literal("text"),
  56. text: z.string(),
  57. })
  58. .openapi({
  59. ref: "Message.Part.Text",
  60. })
  61. export type TextPart = z.infer<typeof TextPart>
  62. export const ReasoningPart = z
  63. .object({
  64. type: z.literal("reasoning"),
  65. text: z.string(),
  66. providerMetadata: z.record(z.any()).optional(),
  67. })
  68. .openapi({
  69. ref: "Message.Part.Reasoning",
  70. })
  71. export type ReasoningPart = z.infer<typeof ReasoningPart>
  72. export const ToolInvocationPart = z
  73. .object({
  74. type: z.literal("tool-invocation"),
  75. toolInvocation: ToolInvocation,
  76. })
  77. .openapi({
  78. ref: "Message.Part.ToolInvocation",
  79. })
  80. export type ToolInvocationPart = z.infer<typeof ToolInvocationPart>
  81. export const SourceUrlPart = z
  82. .object({
  83. type: z.literal("source-url"),
  84. sourceId: z.string(),
  85. url: z.string(),
  86. title: z.string().optional(),
  87. providerMetadata: z.record(z.any()).optional(),
  88. })
  89. .openapi({
  90. ref: "Message.Part.SourceUrl",
  91. })
  92. export type SourceUrlPart = z.infer<typeof SourceUrlPart>
  93. export const FilePart = z
  94. .object({
  95. type: z.literal("file"),
  96. mediaType: z.string(),
  97. filename: z.string().optional(),
  98. url: z.string(),
  99. })
  100. .openapi({
  101. ref: "Message.Part.File",
  102. })
  103. export type FilePart = z.infer<typeof FilePart>
  104. export const StepStartPart = z
  105. .object({
  106. type: z.literal("step-start"),
  107. })
  108. .openapi({
  109. ref: "Message.Part.StepStart",
  110. })
  111. export type StepStartPart = z.infer<typeof StepStartPart>
  112. export const Part = z
  113. .discriminatedUnion("type", [
  114. TextPart,
  115. ReasoningPart,
  116. ToolInvocationPart,
  117. SourceUrlPart,
  118. FilePart,
  119. StepStartPart,
  120. ])
  121. .openapi({
  122. ref: "Message.Part",
  123. })
  124. export type Part = z.infer<typeof Part>
  125. export const Info = z
  126. .object({
  127. id: z.string(),
  128. role: z.enum(["user", "assistant"]),
  129. parts: z.array(Part),
  130. metadata: z
  131. .object({
  132. time: z.object({
  133. created: z.number(),
  134. completed: z.number().optional(),
  135. }),
  136. error: z
  137. .discriminatedUnion("name", [
  138. Provider.AuthError.Schema,
  139. NamedError.Unknown.Schema,
  140. OutputLengthError.Schema,
  141. ])
  142. .optional(),
  143. sessionID: z.string(),
  144. tool: z.record(
  145. z.string(),
  146. z
  147. .object({
  148. title: z.string(),
  149. time: z.object({
  150. start: z.number(),
  151. end: z.number(),
  152. }),
  153. })
  154. .catchall(z.any()),
  155. ),
  156. assistant: z
  157. .object({
  158. system: z.string().array(),
  159. modelID: z.string(),
  160. providerID: z.string(),
  161. path: z.object({
  162. cwd: z.string(),
  163. root: z.string(),
  164. }),
  165. cost: z.number(),
  166. summary: z.boolean().optional(),
  167. tokens: z.object({
  168. input: z.number(),
  169. output: z.number(),
  170. reasoning: z.number(),
  171. cache: z.object({
  172. read: z.number(),
  173. write: z.number(),
  174. }),
  175. }),
  176. })
  177. .optional(),
  178. })
  179. .openapi({ ref: "Message.Metadata" }),
  180. })
  181. .openapi({
  182. ref: "Message.Info",
  183. })
  184. export type Info = z.infer<typeof Info>
  185. export const Event = {
  186. Updated: Bus.event(
  187. "message.updated",
  188. z.object({
  189. info: Info,
  190. }),
  191. ),
  192. PartUpdated: Bus.event(
  193. "message.part.updated",
  194. z.object({ part: Part, sessionID: z.string(), messageID: z.string() }),
  195. ),
  196. }
  197. }