message.ts 6.4 KB

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