question.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { QuestionV2 } from "@opencode-ai/core/question"
  2. import { Effect } from "effect"
  3. import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi"
  4. import { Api } from "../api"
  5. import { QuestionNotFoundError } from "../errors"
  6. import { response } from "../groups/location"
  7. function missingRequest(id: QuestionV2.ID) {
  8. return new QuestionNotFoundError({ requestID: id, message: `Question request not found: ${id}` })
  9. }
  10. export const QuestionHandler = HttpApiBuilder.group(Api, "server.question", (handlers) =>
  11. Effect.gen(function* () {
  12. const withOwnedQuestion = Effect.fnUntraced(function* <A, E>(
  13. sessionID: QuestionV2.Request["sessionID"],
  14. requestID: QuestionV2.ID,
  15. use: (question: QuestionV2.Interface) => Effect.Effect<A, E>,
  16. ) {
  17. const question = yield* QuestionV2.Service
  18. const request = (yield* question.list()).find((request) => request.id === requestID)
  19. if (!request || request.sessionID !== sessionID) return yield* missingRequest(requestID)
  20. return yield* use(question)
  21. })
  22. return handlers
  23. .handle(
  24. "question.request.list",
  25. Effect.fn(function* () {
  26. return yield* response((yield* QuestionV2.Service).list())
  27. }),
  28. )
  29. .handle(
  30. "session.question.list",
  31. Effect.fn(function* (ctx) {
  32. const requests = yield* (yield* QuestionV2.Service).list()
  33. return { data: requests.filter((request) => request.sessionID === ctx.params.sessionID) }
  34. }),
  35. )
  36. .handle(
  37. "session.question.reply",
  38. Effect.fn(function* (ctx) {
  39. yield* withOwnedQuestion(ctx.params.sessionID, ctx.params.requestID, (question) =>
  40. question
  41. .reply({ requestID: ctx.params.requestID, answers: ctx.payload.answers })
  42. .pipe(Effect.catchTag("QuestionV2.NotFoundError", () => missingRequest(ctx.params.requestID))),
  43. )
  44. return HttpApiSchema.NoContent.make()
  45. }),
  46. )
  47. .handle(
  48. "session.question.reject",
  49. Effect.fn(function* (ctx) {
  50. yield* withOwnedQuestion(ctx.params.sessionID, ctx.params.requestID, (question) =>
  51. question
  52. .reject(ctx.params.requestID)
  53. .pipe(Effect.catchTag("QuestionV2.NotFoundError", () => missingRequest(ctx.params.requestID))),
  54. )
  55. return HttpApiSchema.NoContent.make()
  56. }),
  57. )
  58. }),
  59. )