effect.test.ts 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import { expect, test } from "bun:test"
  2. import { DateTime, Effect } from "effect"
  3. import { HttpClient, HttpClientResponse } from "effect/unstable/http"
  4. import { AbsolutePath, Agent, Location, Model, OpenCode, Prompt, Session } from "../src/effect"
  5. test("sessions.get returns the decoded Effect projection", async () => {
  6. const httpClient = HttpClient.make((request) =>
  7. Effect.succeed(HttpClientResponse.fromWeb(request, Response.json(session))),
  8. )
  9. const result = await Effect.gen(function* () {
  10. const client = yield* OpenCode.make({ baseUrl: "http://localhost:3000" })
  11. return yield* client.sessions.get({ sessionID: Session.ID.make("ses_test") })
  12. }).pipe(Effect.provideService(HttpClient.HttpClient, httpClient), Effect.runPromise)
  13. expect(DateTime.toEpochMillis(result.time.created)).toBe(1_717_171_717_000)
  14. })
  15. test("session methods retain decoded Effect inputs and outputs", async () => {
  16. const httpClient = HttpClient.make((request) => {
  17. const url = request.url
  18. if (url.includes("/prompt")) {
  19. return Effect.succeed(HttpClientResponse.fromWeb(request, Response.json(admission)))
  20. }
  21. if (url.includes("/context")) {
  22. return Effect.succeed(HttpClientResponse.fromWeb(request, Response.json({ data: [] })))
  23. }
  24. if (request.method === "POST" && url.endsWith("/api/session")) {
  25. return Effect.succeed(HttpClientResponse.fromWeb(request, Response.json(session)))
  26. }
  27. if (request.method === "POST") {
  28. return Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null, { status: 204 })))
  29. }
  30. return Effect.succeed(
  31. HttpClientResponse.fromWeb(request, Response.json({ data: [session.data], cursor: { next: "next" } })),
  32. )
  33. })
  34. const result = await Effect.gen(function* () {
  35. const client = yield* OpenCode.make({ baseUrl: "http://localhost:3000" })
  36. const page = yield* client.sessions.list({ limit: 10 })
  37. const created = yield* client.sessions.create({
  38. location: Location.Ref.make({ directory: AbsolutePath.make("/tmp/project") }),
  39. })
  40. yield* client.sessions.switchAgent({ sessionID: Session.ID.make("ses_test"), agent: Agent.ID.make("build") })
  41. yield* client.sessions.switchModel({
  42. sessionID: Session.ID.make("ses_test"),
  43. model: Model.Ref.make({ id: "claude", providerID: "anthropic" }),
  44. })
  45. const admitted = yield* client.sessions.prompt({
  46. sessionID: Session.ID.make("ses_test"),
  47. prompt: Prompt.make({ text: "Hello" }),
  48. resume: false,
  49. })
  50. yield* client.sessions.compact({ sessionID: Session.ID.make("ses_test") })
  51. yield* client.sessions.wait({ sessionID: Session.ID.make("ses_test") })
  52. const context = yield* client.sessions.context({ sessionID: Session.ID.make("ses_test") })
  53. return { page, created, admitted, context }
  54. }).pipe(Effect.provideService(HttpClient.HttpClient, httpClient), Effect.runPromise)
  55. expect(DateTime.toEpochMillis(result.page.data[0].time.created)).toBe(1_717_171_717_000)
  56. expect(Object.getPrototypeOf(result.page.data[0])).toBe(Object.prototype)
  57. expect(Object.getPrototypeOf(result.created)).toBe(Object.prototype)
  58. expect(result.created.id).toBe("ses_test")
  59. expect(Object.getPrototypeOf(result.admitted)).toBe(Object.prototype)
  60. expect(Object.getPrototypeOf(result.admitted.prompt)).toBe(Object.prototype)
  61. expect(DateTime.toEpochMillis(result.admitted.timeCreated)).toBe(1_717_171_717_000)
  62. expect(result.context).toEqual([])
  63. })
  64. const session = {
  65. data: {
  66. id: "ses_test",
  67. projectID: "project",
  68. cost: 0,
  69. tokens: {
  70. input: 1,
  71. output: 2,
  72. reasoning: 3,
  73. cache: { read: 4, write: 5 },
  74. },
  75. time: {
  76. created: 1_717_171_717_000,
  77. updated: 1_717_171_717_000,
  78. },
  79. title: "Test",
  80. location: { directory: "/tmp/project" },
  81. },
  82. }
  83. const admission = {
  84. data: {
  85. admittedSeq: 0,
  86. id: "msg_test",
  87. sessionID: "ses_test",
  88. prompt: { text: "Hello" },
  89. delivery: "steer",
  90. timeCreated: 1_717_171_717_000,
  91. },
  92. }