Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174export * as Form from "./form.js"
import { Schema } from "effect"import { ephemeral, inventory } from "./event.js"import { ascending } from "./identifier.js"import { NonNegativeInt, optional, statics } from "./schema.js"
const IDSchema = Schema.String.check(Schema.isStartsWith("frm_")).pipe(Schema.brand("Form.ID"))
export const ID = IDSchema.pipe( statics((schema: typeof IDSchema) => ({ create: (id?: string) => schema.make(id ?? "frm_" + ascending()) })),)export type ID = typeof ID.Type
export const Metadata = Schema.Record(Schema.String, Schema.Unknown).annotate({ identifier: "Form.Metadata" })export type Metadata = typeof Metadata.Type
export const Option = Schema.Struct({ value: Schema.String, label: Schema.String, description: Schema.String.pipe(optional),}).annotate({ identifier: "Form.Option" })export interface Option extends Schema.Schema.Type<typeof Option> {}
// One visibility condition on a field. A field's `when` is a list of conditions that must all// hold (AND) against the current answers for the field to be active. Semantics:// - `value` must match the referenced field's type; against a multiselect answer, `eq` means// "selection includes value" and `neq` means "selection does not include value".// - An unanswered referenced field makes the condition false for both ops.// - `key` must reference a field defined earlier in the form's field list.// Inactive fields are neither required nor answerable.export const When = Schema.Struct({ key: Schema.String, op: Schema.Literals(["eq", "neq"]), value: Schema.Union([Schema.String, Schema.Number, Schema.Boolean]),}).annotate({ identifier: "Form.When" })export interface When extends Schema.Schema.Type<typeof When> {}
const FieldBase = { key: Schema.String, title: Schema.String.pipe(optional), description: Schema.String.pipe(optional), required: Schema.Boolean.pipe(optional), hidden: Schema.Boolean.pipe(optional).annotate({ description: "Skip the interactive authentication prompt and use the default unless an answer is supplied", }), when: Schema.Array(When).pipe(optional),}
export const StringField = Schema.Struct({ ...FieldBase, type: Schema.Literal("string"), format: Schema.Literals(["email", "uri", "date", "date-time"]).pipe(optional), minLength: NonNegativeInt.pipe(optional), maxLength: NonNegativeInt.pipe(optional), pattern: Schema.String.pipe(optional), placeholder: Schema.String.pipe(optional), default: Schema.String.pipe(optional), options: Schema.Array(Option).pipe(optional), custom: Schema.Boolean.pipe(optional),}).annotate({ identifier: "Form.StringField" })export interface StringField extends Schema.Schema.Type<typeof StringField> {}
export const NumberField = Schema.Struct({ ...FieldBase, type: Schema.Literal("number"), minimum: Schema.Number.pipe(optional), maximum: Schema.Number.pipe(optional), default: Schema.Number.pipe(optional),}).annotate({ identifier: "Form.NumberField" })export interface NumberField extends Schema.Schema.Type<typeof NumberField> {}
export const IntegerField = Schema.Struct({ ...FieldBase, type: Schema.Literal("integer"), minimum: Schema.Number.pipe(optional), maximum: Schema.Number.pipe(optional), default: Schema.Number.pipe(optional),}).annotate({ identifier: "Form.IntegerField" })export interface IntegerField extends Schema.Schema.Type<typeof IntegerField> {}
export const BooleanField = Schema.Struct({ ...FieldBase, type: Schema.Literal("boolean"), default: Schema.Boolean.pipe(optional),}).annotate({ identifier: "Form.BooleanField" })export interface BooleanField extends Schema.Schema.Type<typeof BooleanField> {}
export const MultiselectField = Schema.Struct({ ...FieldBase, type: Schema.Literal("multiselect"), options: Schema.Array(Option), minItems: NonNegativeInt.pipe(optional), maxItems: NonNegativeInt.pipe(optional), custom: Schema.Boolean.pipe(optional), default: Schema.Array(Schema.String).pipe(optional),}).annotate({ identifier: "Form.MultiselectField" })export interface MultiselectField extends Schema.Schema.Type<typeof MultiselectField> {}
export const ExternalField = Schema.Struct({ key: Schema.String, type: Schema.Literal("external"), url: Schema.String, title: Schema.String.pipe(optional), description: Schema.String.pipe(optional),}).annotate({ identifier: "Form.ExternalField" })export interface ExternalField extends Schema.Schema.Type<typeof ExternalField> {}
export const Field = Schema.Union([ StringField, NumberField, IntegerField, BooleanField, MultiselectField, ExternalField,]).pipe(Schema.toTaggedUnion("type"), Schema.annotate({ identifier: "Form.Field" }))export type Field = StringField | NumberField | IntegerField | BooleanField | MultiselectField | ExternalField
export const Fields = Schema.NonEmptyArray(Field).annotate({ identifier: "Form.Fields" })export type Fields = typeof Fields.Type
const InfoBase = { id: ID, // This should be typed as SessionID. It is a plain string only because MCP elicitation // temporarily needs the `"global"` sentinel owner, which is not a real session. Once // elicitations can be attributed to real sessions, revert this to SessionID. Do not rely // on non-session owners anywhere else. sessionID: Schema.String, title: Schema.String, metadata: Metadata.pipe(optional),}
export const Info = Schema.Struct({ ...InfoBase, fields: Fields,}).annotate({ identifier: "Form.Info" })export interface Info extends Schema.Schema.Type<typeof Info> {}
export const Value = Schema.Union([Schema.String, Schema.Number, Schema.Boolean, Schema.Array(Schema.String)]).annotate( { identifier: "Form.Value", },)export type Value = typeof Value.Type
export const Answer = Schema.Record(Schema.String, Value).annotate({ identifier: "Form.Answer" })export type Answer = typeof Answer.Type
export const State = Schema.Union([ Schema.Struct({ status: Schema.Literal("pending") }), Schema.Struct({ status: Schema.Literal("answered"), answer: Answer }), Schema.Struct({ status: Schema.Literal("cancelled") }),]) .pipe(Schema.toTaggedUnion("status")) .annotate({ identifier: "Form.State" })export type State = typeof State.Type
export const Detail = Schema.Struct({ ...Info.fields, state: State,}).annotate({ identifier: "Form.Detail" })export interface Detail extends Schema.Schema.Type<typeof Detail> {}
export const Reply = Schema.Struct({ answer: Answer,}).annotate({ identifier: "Form.Reply" })export interface Reply extends Schema.Schema.Type<typeof Reply> {}
const Created = ephemeral({ type: "form.created", schema: { form: Info } })const Replied = ephemeral({ type: "form.replied", schema: { id: ID, sessionID: Schema.String, answer: Answer } })const Cancelled = ephemeral({ type: "form.cancelled", schema: { id: ID, sessionID: Schema.String } })
export const Event = { Created, Replied, Cancelled, Definitions: inventory(Created, Replied, Cancelled) }