| ... | @@ -59,17 +59,7 @@ export const PROVIDER_SEND_TURN_MAX_ATTACHMENTS = 8; | ... | @@ -59,17 +59,7 @@ export const PROVIDER_SEND_TURN_MAX_ATTACHMENTS = 8; |
| 59 | export const PROVIDER_SEND_TURN_MAX_IMAGE_BYTES = 10 * 1024 * 1024; | 59 | export const PROVIDER_SEND_TURN_MAX_IMAGE_BYTES = 10 * 1024 * 1024; |
| 60 | export const PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS = 14_000_000; | 60 | export const PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS = 14_000_000; |
| 61 | | 61 | |
| 62 | function validateImageDataUrl(value: { dataUrl: string }, ctx: z.RefinementCtx): void { | 62 | export const providerSendTurnImageAttachmentSchema = z.object({ |
| 63 | if (!value.dataUrl.startsWith("data:image/")) { | | |
| 64 | ctx.addIssue({ | | |
| 65 | code: z.ZodIssueCode.custom, | | |
| 66 | message: "Image dataUrl must start with data:image/", | | |
| 67 | path: ["dataUrl"], | | |
| 68 | }); | | |
| 69 | } | | |
| 70 | } | | |
| 71 | | | |
| 72 | const providerSendTurnImageAttachmentBaseSchema = z.object({ | | |
| 73 | type: z.literal("image"), | 63 | type: z.literal("image"), |
| 74 | name: z.string().trim().min(1).max(255), | 64 | name: z.string().trim().min(1).max(255), |
| 75 | mimeType: z | 65 | mimeType: z |
| ... | @@ -82,35 +72,30 @@ const providerSendTurnImageAttachmentBaseSchema = z.object({ | ... | @@ -82,35 +72,30 @@ const providerSendTurnImageAttachmentBaseSchema = z.object({ |
| 82 | dataUrl: z.string().trim().min(1).max(PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS), | 72 | dataUrl: z.string().trim().min(1).max(PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS), |
| 83 | }); | 73 | }); |
| 84 | | 74 | |
| 85 | export const providerSendTurnImageAttachmentInputSchema = | | |
| 86 | providerSendTurnImageAttachmentBaseSchema.superRefine(validateImageDataUrl); | | |
| 87 | | | |
| 88 | export const providerSendTurnAttachmentInputSchema = z.discriminatedUnion("type", [ | 75 | export const providerSendTurnAttachmentInputSchema = z.discriminatedUnion("type", [ |
| 89 | providerSendTurnImageAttachmentBaseSchema, | 76 | providerSendTurnImageAttachmentSchema, |
| 90 | ]).superRefine((value, ctx) => { | 77 | ]); |
| 91 | if (value.type === "image") { | | |
| 92 | validateImageDataUrl(value, ctx); | | |
| 93 | } | | |
| 94 | }); | | |
| 95 | | 78 | |
| 96 | export const providerSendTurnInputSchema = z.object({ | 79 | export const providerSendTurnInputSchema = z |
| 97 | sessionId: z.string().min(1), | 80 | .object({ |
| 98 | input: z.string().trim().min(1).max(PROVIDER_SEND_TURN_MAX_INPUT_CHARS).optional(), | 81 | sessionId: z.string().min(1), |
| 99 | attachments: z | 82 | input: z.string().trim().min(1).max(PROVIDER_SEND_TURN_MAX_INPUT_CHARS).optional(), |
| 100 | .array(providerSendTurnAttachmentInputSchema) | 83 | attachments: z |
| 101 | .max(PROVIDER_SEND_TURN_MAX_ATTACHMENTS) | 84 | .array(providerSendTurnAttachmentInputSchema) |
| 102 | .default([]), | 85 | .max(PROVIDER_SEND_TURN_MAX_ATTACHMENTS) |
| 103 | model: z.string().trim().min(1).optional(), | 86 | .default([]), |
| 104 | effort: z.string().trim().min(1).optional(), | 87 | model: z.string().trim().min(1).optional(), |
| 105 | }).superRefine((value, ctx) => { | 88 | effort: z.string().trim().min(1).optional(), |
| 106 | if (!value.input && value.attachments.length === 0) { | 89 | }) |
| 107 | ctx.addIssue({ | 90 | .superRefine((value, ctx) => { |
| 108 | code: z.ZodIssueCode.custom, | 91 | if (!value.input && value.attachments.length === 0) { |
| 109 | message: "Either input text or at least one attachment is required", | 92 | ctx.addIssue({ |
| 110 | path: ["input"], | 93 | code: z.ZodIssueCode.custom, |
| 111 | }); | 94 | message: "Either input text or at least one attachment is required", |
| 112 | } | 95 | path: ["input"], |
| 113 | }); | 96 | }); |
| | 97 | } |
| | 98 | }); |
| 114 | | 99 | |
| 115 | export const providerTurnStartResultSchema = z.object({ | 100 | export const providerTurnStartResultSchema = z.object({ |
| 116 | threadId: z.string().min(1), | 101 | threadId: z.string().min(1), |
| ... | @@ -159,8 +144,7 @@ export type ProviderApprovalDecision = z.infer<typeof providerApprovalDecisionSc | ... | @@ -159,8 +144,7 @@ export type ProviderApprovalDecision = z.infer<typeof providerApprovalDecisionSc |
| 159 | export type ProviderSessionStatus = z.infer<typeof providerSessionStatusSchema>; | 144 | export type ProviderSessionStatus = z.infer<typeof providerSessionStatusSchema>; |
| 160 | export type ProviderSession = z.infer<typeof providerSessionSchema>; | 145 | export type ProviderSession = z.infer<typeof providerSessionSchema>; |
| 161 | export type ProviderSessionStartInput = z.input<typeof providerSessionStartInputSchema>; | 146 | export type ProviderSessionStartInput = z.input<typeof providerSessionStartInputSchema>; |
| 162 | export type ProviderSendTurnImageAttachment = z.infer<typeof providerSendTurnImageAttachmentInputSchema>; | 147 | export type ProviderSendTurnImageAttachment = z.infer<typeof providerSendTurnImageAttachmentSchema>; |
| 163 | export type ProviderSendTurnImageAttachmentInput = z.input<typeof providerSendTurnImageAttachmentInputSchema>; | | |
| 164 | export type ProviderSendTurnAttachment = z.infer<typeof providerSendTurnAttachmentInputSchema>; | 148 | export type ProviderSendTurnAttachment = z.infer<typeof providerSendTurnAttachmentInputSchema>; |
| 165 | export type ProviderSendTurnAttachmentInput = z.input<typeof providerSendTurnAttachmentInputSchema>; | 149 | export type ProviderSendTurnAttachmentInput = z.input<typeof providerSendTurnAttachmentInputSchema>; |
| 166 | export type ProviderSendTurnInput = z.input<typeof providerSendTurnInputSchema>; | 150 | export type ProviderSendTurnInput = z.input<typeof providerSendTurnInputSchema>; |