diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 31e1a71349..550ab17c16 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -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 +// 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, diff --git a/packages/opencode/src/util/named-schema-error.ts b/packages/opencode/src/util/named-schema-error.ts index e144f2f906..d9b92a23cc 100644 --- a/packages/opencode/src/util/named-schema-error.ts +++ b/packages/opencode/src/util/named-schema-error.ts @@ -26,10 +26,17 @@ export function namedSchemaError 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