refactor: replace Schema.Any ZodOverride with Effect schemas for error types

Add EffectSchema to namedSchemaError for HttpApi OpenAPI generation.
Replace Schema.Any + ZodOverride bridges on RetryPart.error and
AssistantMessage.error with proper Effect Schema unions, producing
concrete discriminated union types in the HttpApi spec instead of
unknown.
This commit is contained in:
Kit Langton
2026-04-28 21:56:40 -04:00
parent 967fa4d3bb
commit b6da0a9cda
2 changed files with 21 additions and 6 deletions
+14 -6
View File
@@ -243,8 +243,7 @@ export const RetryPart = Schema.Struct({
...partBase,
type: Schema.Literal("retry"),
attempt: NonNegativeInt,
// APIError is still NamedError-based Zod; bridge via ZodOverride until errors migrate.
error: Schema.Any.annotate({ [ZodOverride]: APIError.Schema }),
error: APIError.EffectSchema,
time: Schema.Struct({
created: NonNegativeInt,
}),
@@ -447,9 +446,7 @@ export type Part =
| RetryPart
| CompactionPart
// Errors are still NamedError-based Zod; bridge via ZodOverride so the derived
// Zod + JSON Schema emit the original discriminatedUnion shape. Migrating the
// error classes to Schema.TaggedErrorClass is a separate slice.
// Zod discriminated union kept for the legacy Hono OpenAPI path.
const AssistantErrorZod = z.discriminatedUnion("name", [
AuthError.Schema,
NamedError.Unknown.Schema,
@@ -461,6 +458,17 @@ const AssistantErrorZod = z.discriminatedUnion("name", [
])
type AssistantError = z.infer<typeof AssistantErrorZod>
// Effect Schema for the same union — used by HttpApi OpenAPI generation.
const AssistantErrorSchema = Schema.Union([
AuthError.EffectSchema,
Schema.Struct({ name: Schema.Literal("UnknownError"), data: Schema.Struct({ message: Schema.String }) }).annotate({ identifier: "UnknownError" }),
OutputLengthError.EffectSchema,
AbortedError.EffectSchema,
StructuredOutputError.EffectSchema,
ContextOverflowError.EffectSchema,
APIError.EffectSchema,
]).annotate({ discriminator: "name" })
// ── Prompt input schemas ─────────────────────────────────────────────────────
//
// Consumers of `SessionPrompt.PromptInput.parts` send part drafts without the
@@ -540,7 +548,7 @@ export const Assistant = Schema.Struct({
created: NonNegativeInt,
completed: Schema.optional(NonNegativeInt),
}),
error: Schema.optional(Schema.Any.annotate({ [ZodOverride]: AssistantErrorZod })),
error: Schema.optional(AssistantErrorSchema),
parentID: MessageID,
modelID: ModelID,
providerID: ProviderID,
@@ -26,10 +26,17 @@ export function namedSchemaError<Tag extends string, Fields extends Schema.Struc
})
.meta({ ref: tag })
// Effect Schema for the wire shape — used by HttpApi OpenAPI generation.
const effectSchema = Schema.Struct({
name: Schema.Literal(tag),
data: dataSchema,
}).annotate({ identifier: tag })
type Data = Schema.Schema.Type<typeof dataSchema>
class NamedSchemaError extends Error {
static readonly Schema = wire
static readonly EffectSchema = effectSchema
static readonly tag = tag
public static isInstance(input: unknown): input is NamedSchemaError {
return typeof input === "object" && input !== null && "name" in input && (input as { name: unknown }).name === tag