The v1 chat completion proxy rejected requests with `role: "tool"` or
array-typed `content` (multimodal image/video payloads) because the
shared zod schemas were too restrictive:
- `ChatRoleSchema` was `z.enum(['system','user','assistant'])` — now
`z.string()` so any role the backend supports passes through. The
router is a proxy and has no reason to constrain which roles are
valid; the upstream provider decides that.
- `ChatMessageSchema.content` was `z.string()` — now
`z.union([z.string(), z.array(z.any()), z.null()]).optional()` to
accept the three shapes the OpenAI spec defines: plain text, an
array of content-part objects (images, video frames, etc.), or null
(e.g. assistant messages that only carry tool_calls). `.passthrough()`
on the message object ensures extra fields like `tool_call_id`,
`name`, `tool_calls`, etc. are forwarded untouched.
- `ChatCompletionChoiceSchema.finish_reason` was `z.string()` — now
`z.string().nullable().optional()` since some providers return null
for streaming chunks or incomplete generations.
Fixes#2, Fixes#3
Co-Authored-By: Claude <noreply@anthropic.com>