index.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { Effect, Schema } from "effect"
  2. const JsonRpcID = Schema.Union([Schema.String, Schema.Number, Schema.Null])
  3. type Json = Schema.Schema.Type<typeof Schema.Json>
  4. export namespace JsonRpc {
  5. export const RequestFields = {
  6. jsonrpc: Schema.Literal("2.0"),
  7. id: Schema.optional(JsonRpcID),
  8. }
  9. export const Request = Schema.Struct({
  10. ...RequestFields,
  11. method: Schema.String,
  12. params: Schema.optional(Schema.Json),
  13. })
  14. export interface Request extends Schema.Schema.Type<typeof Request> {}
  15. export const ErrorObject = Schema.Struct({
  16. code: Schema.Number,
  17. message: Schema.String,
  18. data: Schema.optional(Schema.Json),
  19. })
  20. export const Response = Schema.Struct({
  21. jsonrpc: Schema.Literal("2.0"),
  22. id: JsonRpcID,
  23. result: Schema.optional(Schema.Json),
  24. error: Schema.optional(ErrorObject),
  25. })
  26. export interface Response extends Schema.Schema.Type<typeof Response> {}
  27. export const decodeRequest = Schema.decodeUnknownSync(Request)
  28. export function success(id: Request["id"], result: unknown): Response | undefined {
  29. if (id === undefined) return undefined
  30. return { jsonrpc: "2.0", id, result: result as Json }
  31. }
  32. export function failure(id: Request["id"], error: unknown): Response {
  33. return {
  34. jsonrpc: "2.0",
  35. id: id ?? null,
  36. error: {
  37. code: -32000,
  38. message: error instanceof Error ? error.message : String(error),
  39. },
  40. }
  41. }
  42. }
  43. export namespace Frontend {
  44. export const KeyModifiers = Schema.Struct({
  45. ctrl: Schema.optional(Schema.Boolean),
  46. shift: Schema.optional(Schema.Boolean),
  47. meta: Schema.optional(Schema.Boolean),
  48. super: Schema.optional(Schema.Boolean),
  49. hyper: Schema.optional(Schema.Boolean),
  50. })
  51. export interface KeyModifiers extends Schema.Schema.Type<typeof KeyModifiers> {}
  52. export const Action = Schema.Union([
  53. Schema.Struct({ type: Schema.Literal("typeText"), text: Schema.String }),
  54. Schema.Struct({ type: Schema.Literal("pressKey"), key: Schema.String, modifiers: Schema.optional(KeyModifiers) }),
  55. Schema.Struct({ type: Schema.Literal("pressEnter") }),
  56. Schema.Struct({ type: Schema.Literal("pressArrow"), direction: Schema.Literals(["up", "down", "left", "right"]) }),
  57. Schema.Struct({ type: Schema.Literal("focus"), target: Schema.Number }),
  58. Schema.Struct({ type: Schema.Literal("click"), target: Schema.Number, x: Schema.Number, y: Schema.Number }),
  59. ])
  60. export type Action = Schema.Schema.Type<typeof Action>
  61. export const Element = Schema.Struct({
  62. id: Schema.String,
  63. num: Schema.Number,
  64. x: Schema.Number,
  65. y: Schema.Number,
  66. width: Schema.Number,
  67. height: Schema.Number,
  68. focusable: Schema.Boolean,
  69. focused: Schema.Boolean,
  70. clickable: Schema.Boolean,
  71. editor: Schema.Boolean,
  72. })
  73. export interface Element extends Schema.Schema.Type<typeof Element> {}
  74. export const State = Schema.Struct({
  75. screen: Schema.String,
  76. focused: Schema.Struct({
  77. renderable: Schema.optional(Schema.Number),
  78. editor: Schema.Boolean,
  79. }),
  80. elements: Schema.Array(Element),
  81. actions: Schema.Array(Action),
  82. })
  83. export interface State extends Schema.Schema.Type<typeof State> {}
  84. export const ActionParams = Schema.Struct({ action: Action })
  85. export interface ActionParams extends Schema.Schema.Type<typeof ActionParams> {}
  86. export const Request = Schema.Union([
  87. Schema.Struct({ ...JsonRpc.RequestFields, method: Schema.Literal("ui.action"), params: ActionParams }),
  88. Schema.Struct({
  89. ...JsonRpc.RequestFields,
  90. method: Schema.Literals(["ui.state", "trace.list", "trace.clear", "trace.export"]),
  91. }),
  92. ])
  93. export type Request = Schema.Schema.Type<typeof Request>
  94. export const decodeRequest = Schema.decodeUnknownSync(Request)
  95. export const TraceRecord = Schema.Struct({
  96. id: Schema.Number,
  97. time: Schema.String,
  98. type: Schema.String,
  99. data: Schema.optional(Schema.Json),
  100. })
  101. export interface TraceRecord extends Schema.Schema.Type<typeof TraceRecord> {}
  102. export const TraceList = Schema.Struct({ records: Schema.Array(TraceRecord) })
  103. export interface TraceList extends Schema.Schema.Type<typeof TraceList> {}
  104. }
  105. export namespace Backend {
  106. export const Item = Schema.Union([
  107. Schema.Struct({ type: Schema.Literal("textDelta"), text: Schema.String }),
  108. Schema.Struct({ type: Schema.Literal("reasoningDelta"), text: Schema.String }),
  109. Schema.Struct({ type: Schema.Literal("toolCall"), id: Schema.String, name: Schema.String, input: Schema.Json }),
  110. Schema.Struct({ type: Schema.Literal("raw"), chunk: Schema.Json }),
  111. ])
  112. export type Item = Schema.Schema.Type<typeof Item>
  113. export const FinishReason = Schema.Literals(["stop", "tool-calls", "length", "content-filter"])
  114. export type FinishReason = Schema.Schema.Type<typeof FinishReason>
  115. export const ChunkParams = Schema.Struct({ id: Schema.String, items: Schema.Array(Item) })
  116. export interface ChunkParams extends Schema.Schema.Type<typeof ChunkParams> {}
  117. export const FinishParams = Schema.Struct({
  118. id: Schema.String,
  119. reason: FinishReason.pipe(Schema.withDecodingDefault(Effect.succeed("stop" as const))),
  120. })
  121. export interface FinishParams extends Schema.Schema.Type<typeof FinishParams> {}
  122. export const DisconnectParams = Schema.Struct({ id: Schema.String })
  123. export interface DisconnectParams extends Schema.Schema.Type<typeof DisconnectParams> {}
  124. export const Request = Schema.Union([
  125. Schema.Struct({ ...JsonRpc.RequestFields, method: Schema.Literal("llm.chunk"), params: ChunkParams }),
  126. Schema.Struct({ ...JsonRpc.RequestFields, method: Schema.Literal("llm.finish"), params: FinishParams }),
  127. Schema.Struct({ ...JsonRpc.RequestFields, method: Schema.Literal("llm.disconnect"), params: DisconnectParams }),
  128. Schema.Struct({
  129. ...JsonRpc.RequestFields,
  130. method: Schema.Literals(["llm.attach", "llm.pending", "network.log"]),
  131. }),
  132. ])
  133. export type Request = Schema.Schema.Type<typeof Request>
  134. export const decodeRequest = Schema.decodeUnknownSync(Request)
  135. export const OpenedExchange = Schema.Struct({ id: Schema.String, url: Schema.String, body: Schema.Json })
  136. export interface OpenedExchange extends Schema.Schema.Type<typeof OpenedExchange> {}
  137. export const NetworkLogEntry = Schema.Struct({
  138. time: Schema.Number,
  139. method: Schema.String,
  140. url: Schema.String,
  141. matched: Schema.Boolean,
  142. })
  143. export interface NetworkLogEntry extends Schema.Schema.Type<typeof NetworkLogEntry> {}
  144. }
  145. export * as SimulationProtocol from "./index"