question.ts 3.1 KB

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