session-message.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. export * as SessionMessage from "./session-message"
  2. import { Schema } from "effect"
  3. import { optional } from "./schema"
  4. import { ProviderMetadata, ToolContent } from "./llm"
  5. import { Model } from "./model"
  6. import { FileAttachment, Prompt } from "./prompt"
  7. import { DateTimeUtcFromMillis, RelativePath, statics } from "./schema"
  8. import { SessionID } from "./session-id"
  9. import { ascending } from "./identifier"
  10. export const ID = Schema.String.check(Schema.isStartsWith("msg_")).pipe(
  11. Schema.brand("Session.Message.ID"),
  12. statics((schema) => ({ create: () => schema.make("msg_" + ascending()) })),
  13. )
  14. export type ID = typeof ID.Type
  15. export interface UnknownError extends Schema.Schema.Type<typeof UnknownError> {}
  16. export const UnknownError = Schema.Struct({
  17. type: Schema.Literal("unknown"),
  18. message: Schema.String,
  19. }).annotate({ identifier: "Session.Error.Unknown" })
  20. const Base = {
  21. id: ID,
  22. metadata: Schema.Record(Schema.String, Schema.Unknown).pipe(optional),
  23. time: Schema.Struct({ created: DateTimeUtcFromMillis }),
  24. }
  25. export interface AgentSwitched extends Schema.Schema.Type<typeof AgentSwitched> {}
  26. export const AgentSwitched = Schema.Struct({
  27. ...Base,
  28. type: Schema.Literal("agent-switched"),
  29. agent: Schema.String,
  30. }).annotate({ identifier: "Session.Message.AgentSwitched" })
  31. export interface ModelSwitched extends Schema.Schema.Type<typeof ModelSwitched> {}
  32. export const ModelSwitched = Schema.Struct({
  33. ...Base,
  34. type: Schema.Literal("model-switched"),
  35. model: Model.Ref,
  36. }).annotate({ identifier: "Session.Message.ModelSwitched" })
  37. export interface User extends Schema.Schema.Type<typeof User> {}
  38. export const User = Schema.Struct({
  39. ...Base,
  40. text: Prompt.fields.text,
  41. files: Prompt.fields.files,
  42. agents: Prompt.fields.agents,
  43. type: Schema.Literal("user"),
  44. }).annotate({ identifier: "Session.Message.User" })
  45. export interface Synthetic extends Schema.Schema.Type<typeof Synthetic> {}
  46. export const Synthetic = Schema.Struct({
  47. ...Base,
  48. sessionID: SessionID,
  49. text: Schema.String,
  50. type: Schema.Literal("synthetic"),
  51. }).annotate({ identifier: "Session.Message.Synthetic" })
  52. export interface System extends Schema.Schema.Type<typeof System> {}
  53. export const System = Schema.Struct({
  54. ...Base,
  55. type: Schema.Literal("system"),
  56. text: Schema.String,
  57. }).annotate({ identifier: "Session.Message.System" })
  58. export interface Shell extends Schema.Schema.Type<typeof Shell> {}
  59. export const Shell = Schema.Struct({
  60. ...Base,
  61. type: Schema.Literal("shell"),
  62. callID: Schema.String,
  63. command: Schema.String,
  64. output: Schema.String,
  65. time: Schema.Struct({
  66. created: DateTimeUtcFromMillis,
  67. completed: DateTimeUtcFromMillis.pipe(optional),
  68. }),
  69. }).annotate({ identifier: "Session.Message.Shell" })
  70. export interface ToolStatePending extends Schema.Schema.Type<typeof ToolStatePending> {}
  71. export const ToolStatePending = Schema.Struct({
  72. status: Schema.Literal("pending"),
  73. input: Schema.String,
  74. }).annotate({ identifier: "Session.Message.ToolState.Pending" })
  75. export interface ToolStateRunning extends Schema.Schema.Type<typeof ToolStateRunning> {}
  76. export const ToolStateRunning = Schema.Struct({
  77. status: Schema.Literal("running"),
  78. input: Schema.Record(Schema.String, Schema.Unknown),
  79. structured: Schema.Record(Schema.String, Schema.Unknown),
  80. content: ToolContent.pipe(Schema.Array),
  81. }).annotate({ identifier: "Session.Message.ToolState.Running" })
  82. export interface ToolStateCompleted extends Schema.Schema.Type<typeof ToolStateCompleted> {}
  83. export const ToolStateCompleted = Schema.Struct({
  84. status: Schema.Literal("completed"),
  85. input: Schema.Record(Schema.String, Schema.Unknown),
  86. attachments: FileAttachment.pipe(Schema.Array, optional),
  87. content: ToolContent.pipe(Schema.Array),
  88. outputPaths: Schema.Array(Schema.String).pipe(optional),
  89. structured: Schema.Record(Schema.String, Schema.Unknown),
  90. result: Schema.Unknown.pipe(optional),
  91. }).annotate({ identifier: "Session.Message.ToolState.Completed" })
  92. export interface ToolStateError extends Schema.Schema.Type<typeof ToolStateError> {}
  93. export const ToolStateError = Schema.Struct({
  94. status: Schema.Literal("error"),
  95. input: Schema.Record(Schema.String, Schema.Unknown),
  96. content: ToolContent.pipe(Schema.Array),
  97. structured: Schema.Record(Schema.String, Schema.Unknown),
  98. error: UnknownError,
  99. result: Schema.Unknown.pipe(optional),
  100. }).annotate({ identifier: "Session.Message.ToolState.Error" })
  101. export const ToolState = Schema.Union([ToolStatePending, ToolStateRunning, ToolStateCompleted, ToolStateError]).pipe(
  102. Schema.toTaggedUnion("status"),
  103. )
  104. export type ToolState = ToolStatePending | ToolStateRunning | ToolStateCompleted | ToolStateError
  105. export interface AssistantTool extends Schema.Schema.Type<typeof AssistantTool> {}
  106. export const AssistantTool = Schema.Struct({
  107. type: Schema.Literal("tool"),
  108. id: Schema.String,
  109. name: Schema.String,
  110. provider: Schema.Struct({
  111. executed: Schema.Boolean,
  112. metadata: ProviderMetadata.pipe(optional),
  113. resultMetadata: ProviderMetadata.pipe(optional),
  114. }).pipe(optional),
  115. state: ToolState,
  116. time: Schema.Struct({
  117. created: DateTimeUtcFromMillis,
  118. ran: DateTimeUtcFromMillis.pipe(optional),
  119. completed: DateTimeUtcFromMillis.pipe(optional),
  120. pruned: DateTimeUtcFromMillis.pipe(optional),
  121. }),
  122. }).annotate({ identifier: "Session.Message.Assistant.Tool" })
  123. export interface AssistantText extends Schema.Schema.Type<typeof AssistantText> {}
  124. export const AssistantText = Schema.Struct({
  125. type: Schema.Literal("text"),
  126. id: Schema.String,
  127. text: Schema.String,
  128. }).annotate({ identifier: "Session.Message.Assistant.Text" })
  129. export interface AssistantReasoning extends Schema.Schema.Type<typeof AssistantReasoning> {}
  130. export const AssistantReasoning = Schema.Struct({
  131. type: Schema.Literal("reasoning"),
  132. id: Schema.String,
  133. text: Schema.String,
  134. providerMetadata: ProviderMetadata.pipe(optional),
  135. time: Schema.Struct({
  136. created: DateTimeUtcFromMillis,
  137. completed: DateTimeUtcFromMillis.pipe(optional),
  138. }).pipe(optional),
  139. }).annotate({ identifier: "Session.Message.Assistant.Reasoning" })
  140. export const AssistantContent = Schema.Union([AssistantText, AssistantReasoning, AssistantTool]).pipe(
  141. Schema.toTaggedUnion("type"),
  142. )
  143. export type AssistantContent = AssistantText | AssistantReasoning | AssistantTool
  144. export interface Assistant extends Schema.Schema.Type<typeof Assistant> {}
  145. export const Assistant = Schema.Struct({
  146. ...Base,
  147. type: Schema.Literal("assistant"),
  148. agent: Schema.String,
  149. model: Model.Ref,
  150. content: AssistantContent.pipe(Schema.Array),
  151. snapshot: Schema.Struct({
  152. start: Schema.String.pipe(optional),
  153. end: Schema.String.pipe(optional),
  154. files: Schema.Array(RelativePath).pipe(optional),
  155. }).pipe(optional),
  156. finish: Schema.String.pipe(optional),
  157. cost: Schema.Finite.pipe(optional),
  158. tokens: Schema.Struct({
  159. input: Schema.Finite,
  160. output: Schema.Finite,
  161. reasoning: Schema.Finite,
  162. cache: Schema.Struct({ read: Schema.Finite, write: Schema.Finite }),
  163. }).pipe(optional),
  164. error: UnknownError.pipe(optional),
  165. time: Schema.Struct({
  166. created: DateTimeUtcFromMillis,
  167. completed: DateTimeUtcFromMillis.pipe(optional),
  168. }),
  169. }).annotate({ identifier: "Session.Message.Assistant" })
  170. export interface Compaction extends Schema.Schema.Type<typeof Compaction> {}
  171. export const Compaction = Schema.Struct({
  172. type: Schema.Literal("compaction"),
  173. reason: Schema.Literals(["auto", "manual"]),
  174. summary: Schema.String,
  175. recent: Schema.String,
  176. ...Base,
  177. }).annotate({ identifier: "Session.Message.Compaction" })
  178. export const Message = Schema.Union([
  179. AgentSwitched,
  180. ModelSwitched,
  181. User,
  182. Synthetic,
  183. System,
  184. Shell,
  185. Assistant,
  186. Compaction,
  187. ])
  188. .pipe(Schema.toTaggedUnion("type"))
  189. .annotate({ identifier: "Session.Message" })
  190. export type Message = AgentSwitched | ModelSwitched | User | Synthetic | System | Shell | Assistant | Compaction
  191. export type Type = Message["type"]