fix(image): disable attachment resizing by default

This commit is contained in:
Aiden Cline
2026-05-12 17:16:13 -05:00
parent 2cb697b720
commit 9422b49cbf
5 changed files with 68 additions and 4 deletions

View File

@@ -4,8 +4,13 @@ import { Schema } from "effect"
import { PositiveInt } from "@opencode-ai/core/schema"
export const Image = Schema.Struct({
enforce_limits: Schema.optional(Schema.Boolean).annotate({
description:
"Enforce image attachment size limits before sending images to the model. When false, images pass through unchanged (default: false)",
}),
auto_resize: Schema.optional(Schema.Boolean).annotate({
description: "Resize images before sending them to the model when they exceed configured limits (default: true)",
description:
"Resize images before sending them to the model when they exceed configured limits. Requires enforce_limits to be true (default: false)",
}),
max_width: Schema.optional(PositiveInt).annotate({
description: "Maximum image width before resizing or rejecting the attachment (default: 2000)",

View File

@@ -6,7 +6,8 @@ import { Context, Effect, Layer, Schema } from "effect"
const MAX_BASE64_BYTES = 4.5 * 1024 * 1024
const MAX_WIDTH = 2000
const MAX_HEIGHT = 2000
const AUTO_RESIZE = true
const ENFORCE_LIMITS = false
const AUTO_RESIZE = false
const JPEG_QUALITIES = [80, 85, 70, 55, 40]
const log = Log.create({ service: "image" })
@@ -76,11 +77,13 @@ export const layer = Layer.effect(
const normalize = Effect.fn("Image.normalize")(function* (input: MessageV2.FilePart) {
const image = (yield* config.get()).attachment?.image
const info = {
enforceLimits: image?.enforce_limits ?? ENFORCE_LIMITS,
autoResize: image?.auto_resize ?? AUTO_RESIZE,
maxWidth: image?.max_width ?? MAX_WIDTH,
maxHeight: image?.max_height ?? MAX_HEIGHT,
maxBase64Bytes: image?.max_base64_bytes ?? MAX_BASE64_BYTES,
}
if (!info.enforceLimits) return input
if (!input.url.startsWith("data:") || !input.url.includes(";base64,"))
return yield* new InvalidDataUrlError({ url: input.url })

View File

@@ -6,11 +6,24 @@ import { TestConfig } from "../fixture/config"
import { testEffect } from "../lib/effect"
const it = testEffect(Layer.mergeAll(Image.layer.pipe(Layer.provide(TestConfig.layer()))))
const enforcing = testEffect(
Layer.mergeAll(
Image.layer.pipe(
Layer.provide(
TestConfig.layer({
get: () => Effect.succeed({ attachment: { image: { enforce_limits: true, auto_resize: true } } }),
}),
),
),
),
)
const tiny = testEffect(
Layer.mergeAll(
Image.layer.pipe(
Layer.provide(
TestConfig.layer({ get: () => Effect.succeed({ attachment: { image: { max_base64_bytes: 1 } } }) }),
TestConfig.layer({
get: () => Effect.succeed({ attachment: { image: { enforce_limits: true, max_base64_bytes: 1 } } }),
}),
),
),
),
@@ -28,7 +41,16 @@ function part(mime: string, data: string) {
}
describe("Image", () => {
it.effect("normalizes generated png and jpeg attachments", () =>
it.effect("passes images through by default without loading the resizer", () =>
Effect.gen(function* () {
const image = yield* Image.Service
const input = part("image/png", "not-valid-image-data")
expect(yield* image.normalize(input)).toEqual(input)
}),
)
enforcing.effect("normalizes generated png and jpeg attachments when limit enforcement is enabled", () =>
Effect.gen(function* () {
const photon = yield* Effect.promise(() => import("@silvia-odwyer/photon-node"))
const source = new photon.PhotonImage(

View File

@@ -1143,6 +1143,7 @@ export type McpRemoteConfig = {
export type LayoutConfig = "auto" | "stretch"
export type ImageAttachmentConfig = {
enforce_limits?: boolean
auto_resize?: boolean
max_width?: number
max_height?: number

View File

@@ -345,6 +345,39 @@ You can manage the tools an LLM can use through the `tools` option.
---
### Attachments
You can configure how image attachments are processed before they are sent to the model through the `attachment.image` option.
By default OpenCode does not enforce image attachment limits and does not resize images. Images pass through unchanged unless you explicitly enable limit enforcement.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"attachment": {
"image": {
"enforce_limits": true,
"auto_resize": false,
"max_width": 2000,
"max_height": 2000,
"max_base64_bytes": 4718592
}
}
}
```
Available options:
- `enforce_limits` - Enforce configured image limits before sending images to the model. Defaults to `false`, which passes images through unchanged.
- `auto_resize` - Resize images that exceed configured limits. This only applies when `enforce_limits` is `true`. Defaults to `false`.
- `max_width` - Maximum image width when limit enforcement is enabled. Defaults to `2000`.
- `max_height` - Maximum image height when limit enforcement is enabled. Defaults to `2000`.
- `max_base64_bytes` - Maximum base64 payload size when limit enforcement is enabled. Defaults to `4718592`.
When `enforce_limits` is `true` and `auto_resize` is `false`, images over the configured limits are omitted. When both are `true`, OpenCode attempts to resize oversized images before omitting them.
---
### Models
You can configure the providers and models you want to use in your OpenCode config through the `provider`, `model` and `small_model` options.