feat(server): add form routes (#35099)
Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
This commit is contained in:
parent
3ce5e9800d
commit
d9bf30fc22
16 changed files with 3080 additions and 436 deletions
|
|
@ -6,6 +6,7 @@ import { ProviderHandler } from "./handlers/provider"
|
|||
import { SessionHandler } from "./handlers/session"
|
||||
import { PermissionHandler } from "./handlers/permission"
|
||||
import { FileSystemHandler } from "./handlers/fs"
|
||||
import { FormHandler } from "./handlers/form"
|
||||
import { CommandHandler } from "./handlers/command"
|
||||
import { SkillHandler } from "./handlers/skill"
|
||||
import { EventHandler } from "./handlers/event"
|
||||
|
|
@ -37,6 +38,7 @@ export const handlers = Layer.mergeAll(
|
|||
McpHandler,
|
||||
CredentialHandler,
|
||||
ProjectHandler,
|
||||
FormHandler,
|
||||
PermissionHandler,
|
||||
FileSystemHandler,
|
||||
CommandHandler,
|
||||
|
|
|
|||
123
packages/server/src/handlers/form.ts
Normal file
123
packages/server/src/handlers/form.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
import { Form } from "@opencode-ai/core/form"
|
||||
import {
|
||||
ConflictError,
|
||||
FormAlreadySettledError,
|
||||
FormInvalidAnswerError,
|
||||
FormNotFoundError,
|
||||
InvalidRequestError,
|
||||
} from "@opencode-ai/protocol/errors"
|
||||
import { Effect } from "effect"
|
||||
import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi"
|
||||
import { Api } from "../api"
|
||||
import { response } from "../location"
|
||||
|
||||
function missingForm(id: Form.ID) {
|
||||
return new FormNotFoundError({ id, message: `Form not found: ${id}` })
|
||||
}
|
||||
|
||||
export const FormHandler = HttpApiBuilder.group(Api, "server.form", (handlers) =>
|
||||
Effect.gen(function* () {
|
||||
const requireOwnedForm = Effect.fnUntraced(function* (sessionID: Form.Info["sessionID"], formID: Form.ID) {
|
||||
const form = yield* Form.Service
|
||||
const info = yield* form.get(formID).pipe(Effect.catchTag("Form.NotFoundError", () => missingForm(formID)))
|
||||
if (info.sessionID !== sessionID) return yield* missingForm(formID)
|
||||
return { form, info }
|
||||
})
|
||||
|
||||
return handlers
|
||||
.handle(
|
||||
"form.request.list",
|
||||
Effect.fn(function* () {
|
||||
const form = yield* Form.Service
|
||||
return yield* response(form.list())
|
||||
}),
|
||||
)
|
||||
.handle(
|
||||
"session.form.list",
|
||||
Effect.fn(function* (ctx) {
|
||||
const form = yield* Form.Service
|
||||
const forms = yield* form.list({ sessionID: ctx.params.sessionID })
|
||||
return { data: forms }
|
||||
}),
|
||||
)
|
||||
.handle(
|
||||
"session.form.create",
|
||||
Effect.fn(function* (ctx) {
|
||||
const form = yield* Form.Service
|
||||
const common = {
|
||||
id: ctx.payload.id,
|
||||
sessionID: ctx.params.sessionID,
|
||||
title: ctx.payload.title,
|
||||
metadata: ctx.payload.metadata,
|
||||
}
|
||||
const input = yield* (() => {
|
||||
if (ctx.payload.mode === "form") {
|
||||
if (!ctx.payload.fields) {
|
||||
return new InvalidRequestError({ message: "Form fields are required", field: "fields" })
|
||||
}
|
||||
return Effect.succeed({ ...common, mode: "form" as const, fields: ctx.payload.fields })
|
||||
}
|
||||
if (!ctx.payload.url) return new InvalidRequestError({ message: "Form URL is required", field: "url" })
|
||||
return Effect.succeed({ ...common, mode: "url" as const, url: ctx.payload.url })
|
||||
})()
|
||||
|
||||
const created = yield* form
|
||||
.create(input)
|
||||
.pipe(
|
||||
Effect.catchTag(
|
||||
"Form.AlreadyExistsError",
|
||||
(error) => new ConflictError({ resource: error.id, message: error.message }),
|
||||
),
|
||||
)
|
||||
return { data: created }
|
||||
}),
|
||||
)
|
||||
.handle(
|
||||
"session.form.get",
|
||||
Effect.fn(function* (ctx) {
|
||||
const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID)
|
||||
return { data: owned.info }
|
||||
}),
|
||||
)
|
||||
.handle(
|
||||
"session.form.state",
|
||||
Effect.fn(function* (ctx) {
|
||||
const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID)
|
||||
const data = yield* owned.form
|
||||
.state(ctx.params.formID)
|
||||
.pipe(Effect.catchTag("Form.NotFoundError", () => missingForm(ctx.params.formID)))
|
||||
return { data }
|
||||
}),
|
||||
)
|
||||
.handle(
|
||||
"session.form.reply",
|
||||
Effect.fn(function* (ctx) {
|
||||
const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID)
|
||||
yield* owned.form.reply({ id: ctx.params.formID, answer: ctx.payload.answer }).pipe(
|
||||
Effect.catchTags({
|
||||
"Form.AlreadySettledError": (error) =>
|
||||
new FormAlreadySettledError({ id: error.id, message: error.message }),
|
||||
"Form.InvalidAnswerError": (error) =>
|
||||
new FormInvalidAnswerError({ id: error.id, message: error.message }),
|
||||
"Form.NotFoundError": () => missingForm(ctx.params.formID),
|
||||
}),
|
||||
)
|
||||
return HttpApiSchema.NoContent.make()
|
||||
}),
|
||||
)
|
||||
.handle(
|
||||
"session.form.cancel",
|
||||
Effect.fn(function* (ctx) {
|
||||
const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID)
|
||||
yield* owned.form.cancel(ctx.params.formID).pipe(
|
||||
Effect.catchTags({
|
||||
"Form.AlreadySettledError": (error) =>
|
||||
new FormAlreadySettledError({ id: error.id, message: error.message }),
|
||||
"Form.NotFoundError": () => missingForm(ctx.params.formID),
|
||||
}),
|
||||
)
|
||||
return HttpApiSchema.NoContent.make()
|
||||
}),
|
||||
)
|
||||
}),
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue