promise.test.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { expect, test } from "bun:test"
  2. import { isUnauthorizedError, OpenCode } from "../src"
  3. test("sessions.get returns the wire projection", async () => {
  4. const client = OpenCode.make({
  5. baseUrl: "http://localhost:3000",
  6. fetch: async (input) => {
  7. expect(typeof input === "string" ? input : input instanceof URL ? input.href : input.url).toBe(
  8. "http://localhost:3000/api/session/ses_test",
  9. )
  10. return Response.json(session)
  11. },
  12. })
  13. const result = await client.sessions.get({ sessionID: "ses_test" })
  14. expect(result.time.created).toBe(1_717_171_717_000)
  15. })
  16. test("session methods use the public HTTP contract", async () => {
  17. const requests: Array<{ url: string; init?: RequestInit }> = []
  18. const client = OpenCode.make({
  19. baseUrl: "http://localhost:3000",
  20. fetch: async (input, init) => {
  21. const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url
  22. requests.push({ url, init })
  23. if (url.includes("/prompt")) return Response.json(admission)
  24. if (url.includes("/context")) return Response.json({ data: [] })
  25. if (init?.method === "POST" && url.endsWith("/api/session")) return Response.json(session)
  26. if (init?.method === "POST") return new Response(null, { status: 204 })
  27. return Response.json({ data: [session.data], cursor: { next: "next" } })
  28. },
  29. })
  30. const page = await client.sessions.list({ limit: "10", order: "desc" })
  31. const created = await client.sessions.create({ location: { directory: "/tmp/project" } })
  32. await client.sessions.switchAgent({ sessionID: "ses_test", agent: "build" })
  33. await client.sessions.switchModel({
  34. sessionID: "ses_test",
  35. model: { id: "claude", providerID: "anthropic" },
  36. })
  37. const admitted = await client.sessions.prompt({
  38. sessionID: "ses_test",
  39. prompt: { text: "Hello" },
  40. resume: false,
  41. })
  42. await client.sessions.compact({ sessionID: "ses_test" })
  43. await client.sessions.wait({ sessionID: "ses_test" })
  44. const context = await client.sessions.context({ sessionID: "ses_test" })
  45. expect(page.cursor.next).toBe("next")
  46. expect(created.id).toBe("ses_test")
  47. expect(admitted.id).toBe("msg_test")
  48. expect(context).toEqual([])
  49. expect(requests.map((request) => [request.init?.method, request.url])).toEqual([
  50. ["GET", "http://localhost:3000/api/session?limit=10&order=desc"],
  51. ["POST", "http://localhost:3000/api/session"],
  52. ["POST", "http://localhost:3000/api/session/ses_test/agent"],
  53. ["POST", "http://localhost:3000/api/session/ses_test/model"],
  54. ["POST", "http://localhost:3000/api/session/ses_test/prompt"],
  55. ["POST", "http://localhost:3000/api/session/ses_test/compact"],
  56. ["POST", "http://localhost:3000/api/session/ses_test/wait"],
  57. ["GET", "http://localhost:3000/api/session/ses_test/context"],
  58. ])
  59. const body = requests[4]?.init?.body
  60. if (typeof body !== "string") throw new Error("Expected JSON request body")
  61. expect(JSON.parse(body)).toEqual({
  62. prompt: { text: "Hello" },
  63. resume: false,
  64. })
  65. })
  66. test("middleware errors remain declared client errors", async () => {
  67. const client = OpenCode.make({
  68. baseUrl: "http://localhost:3000",
  69. fetch: async () =>
  70. Response.json({ _tag: "UnauthorizedError", message: "Authentication required" }, { status: 401 }),
  71. })
  72. try {
  73. await client.sessions.create({})
  74. throw new Error("Expected request to fail")
  75. } catch (error) {
  76. expect(isUnauthorizedError(error)).toBe(true)
  77. }
  78. })
  79. const session = {
  80. data: {
  81. id: "ses_test",
  82. projectID: "project",
  83. cost: 0,
  84. tokens: {
  85. input: 1,
  86. output: 2,
  87. reasoning: 3,
  88. cache: { read: 4, write: 5 },
  89. },
  90. time: {
  91. created: 1_717_171_717_000,
  92. updated: 1_717_171_717_000,
  93. },
  94. title: "Test",
  95. location: { directory: "/tmp/project" },
  96. },
  97. }
  98. const admission = {
  99. data: {
  100. admittedSeq: 0,
  101. id: "msg_test",
  102. sessionID: "ses_test",
  103. prompt: { text: "Hello" },
  104. delivery: "steer",
  105. timeCreated: 1_717_171_717_000,
  106. },
  107. }