question.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. export * as Question from "./question"
  2. import { Schema } from "effect"
  3. import { define, inventory } from "./event"
  4. import { ascending } from "./identifier"
  5. import { SessionID } from "./session-id"
  6. import { withStatics } from "./schema"
  7. export const ID = Schema.String.check(Schema.isStartsWith("que")).pipe(
  8. Schema.brand("QuestionV2.ID"),
  9. withStatics((schema) => ({ ascending: (id?: string) => schema.make(id ?? "que_" + ascending()) })),
  10. )
  11. export type ID = typeof ID.Type
  12. export const Option = Schema.Struct({
  13. label: Schema.String.annotate({ description: "Display text (1-5 words, concise)" }),
  14. description: Schema.String.annotate({ description: "Explanation of choice" }),
  15. }).annotate({ identifier: "QuestionV2.Option" })
  16. export type Option = typeof Option.Type
  17. const base = {
  18. question: Schema.String.annotate({ description: "Complete question" }),
  19. header: Schema.String.annotate({ description: "Very short label (max 30 chars)" }),
  20. options: Schema.Array(Option).annotate({ description: "Available choices" }),
  21. multiple: Schema.Boolean.pipe(Schema.optional).annotate({ description: "Allow selecting multiple choices" }),
  22. }
  23. export const Info = Schema.Struct({
  24. ...base,
  25. custom: Schema.Boolean.pipe(Schema.optional).annotate({
  26. description: "Allow typing a custom answer (default: true)",
  27. }),
  28. }).annotate({ identifier: "QuestionV2.Info" })
  29. export type Info = typeof Info.Type
  30. export const Prompt = Schema.Struct(base).annotate({ identifier: "QuestionV2.Prompt" })
  31. export type Prompt = typeof Prompt.Type
  32. export const Tool = Schema.Struct({
  33. messageID: Schema.String,
  34. callID: Schema.String,
  35. }).annotate({ identifier: "QuestionV2.Tool" })
  36. export type Tool = typeof Tool.Type
  37. export const Request = Schema.Struct({
  38. id: ID,
  39. sessionID: SessionID,
  40. questions: Schema.Array(Info).annotate({ description: "Questions to ask" }),
  41. tool: Tool.pipe(Schema.optional),
  42. }).annotate({ identifier: "QuestionV2.Request" })
  43. export type Request = typeof Request.Type
  44. export const Answer = Schema.Array(Schema.String).annotate({ identifier: "QuestionV2.Answer" })
  45. export type Answer = typeof Answer.Type
  46. export const Reply = Schema.Struct({
  47. answers: Schema.Array(Answer).annotate({
  48. description: "User answers in order of questions (each answer is an array of selected labels)",
  49. }),
  50. }).annotate({ identifier: "QuestionV2.Reply" })
  51. export type Reply = typeof Reply.Type
  52. const Asked = define({ type: "question.v2.asked", schema: Request.fields })
  53. const Replied = define({
  54. type: "question.v2.replied",
  55. schema: {
  56. sessionID: SessionID,
  57. requestID: ID,
  58. answers: Schema.Array(Answer),
  59. },
  60. })
  61. const Rejected = define({
  62. type: "question.v2.rejected",
  63. schema: {
  64. sessionID: SessionID,
  65. requestID: ID,
  66. },
  67. })
  68. export const Event = { Asked, Replied, Rejected, Definitions: inventory(Asked, Replied, Rejected) }