Skip to content

feat(core): make image_generate opt-in with one experimental config field - #60096

Merged
rekram1-node merged 2 commits into
devfrom
image-tool-optin
Oct 29, 2026
Merged

rekram1-node merged 2 commits into
devfrom
image-tool-optin

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

The built-in image_generate tool is now off by default. One config field turns it on and can optionally pick its default model:

 {
   "experimental": {
+    "image_generate": true
   }
 }
 {
   "experimental": {
-    "image_model": "openai/gpt-image-2",
+    "image_generate": { "model": "openai/gpt-image-2#hd" }
   }
 }
  • absent or false: tool off
  • true or {}: tool on, model picked automatically (newest image model from the session's provider, otherwise the newest one overall)
  • { "model": "providerID/modelID" } (a #variant is allowed): tool on with that default. If it can't serve a call (unavailable, missing variant, or no image input for edits) it falls back to automatic selection and says so, same as before.

This replaces experimental.image_model. That field hasn't shipped in a release, so there's no alias. Either way the tool only shows up while a connected provider has an image model.

Why I made it opt-in: the tool is new, and it costs a few hundred tokens of tool schema on every request whether or not anyone wants an image. That's my estimate of roughly 450 tokens from the description and parameter text. Agents have also overused it in benchmarks. Image generation also isn't something most coding sessions need, so it's common to leave it out of a coding toolset. I'd rather keep it opt-in while it settles.

The field is read from the newest config document that sets it, so a later config that sets other experimental options doesn't hide it, and the tool list reloads when the config changes.

Visual

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="72" viewBox="0 0 240 72" fill="none">
  <style>
    .knob { animation: knob 4s ease-in-out infinite; }
    .track { animation: track 4s ease-in-out infinite; }
    .tile { animation: tile 4s ease-in-out infinite; }
    @keyframes knob { 0%, 15% { transform: translateX(-20px); } 30%, 100% { transform: translateX(0); } }
    @keyframes track { 0%, 15% { fill-opacity: 0.08; } 30%, 100% { fill-opacity: 0.35; } }
    @keyframes tile { 0%, 35% { opacity: 0; transform: translateY(4px); } 50%, 90% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(0); } }
    @media (prefers-reduced-motion: reduce) { .knob, .track, .tile { animation: none; } }
  </style>
  <rect class="track" x="40" y="24" width="48" height="24" rx="12" fill="currentColor" fill-opacity="0.35" stroke="currentColor" stroke-opacity="0.6"/>
  <circle class="knob" cx="76" cy="36" r="9" fill="currentColor"/>
  <path d="M108 36h20" stroke="currentColor" stroke-opacity="0.4" stroke-width="2" stroke-linecap="round" stroke-dasharray="3 4"/>
  <g class="tile">
    <rect x="144" y="14" width="56" height="44" rx="6" stroke="currentColor" stroke-width="2"/>
    <circle cx="160" cy="28" r="5" fill="currentColor" fill-opacity="0.5"/>
    <path d="M148 52l14-14 10 10 8-6 16 10" stroke="currentColor" stroke-opacity="0.7" stroke-width="2" stroke-linejoin="round"/>
  </g>
</svg>

Verification

  • bun test test/tool-image-generate.test.ts test/config/normalization.test.ts in packages/core (57 pass, covering true, false, {}, { model }, invalid values, and the tool only being offered when enabled)
  • bun run typecheck:tsc in packages/core
  • bun run generate in packages/client and packages/protocol, then bun run check:generated in packages/protocol
  • bun run check at the repo root

Added by the opencode bot (AI-generated).

Public API: experimental.image_generate (boolean | { model? }, default off) replaces experimental.image_model; image_generate tool is now opt-in

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. The gate follows the same ConfigEntryObserver + ctx.tool.reload() pattern as the todo tool's flag. It is read per field like image_model and checked inside the transform together with the existing image-model check. I checked it with the image-generate and config-normalisation tests (57 pass; the new test shows the tool appearing and disappearing as the flag flips) and typecheck:tsc in packages/core. I couldn't check it end to end because the simulated provider has no image model.

Public API: adds the optional config key experimental.image_generate (boolean, defaults to false) to the schema, the OpenAPI spec and the generated client types. Existing configs still validate, but this changes behaviour: anyone who relied on image_generate appearing on its own with an image-capable provider now needs to set experimental.image_generate: true. experimental.image_model alone no longer turns the tool on.

No blocking concerns.

@rekram1-node rekram1-node changed the title feat(core): make image_generate opt-in behind experimental.image_generate feat(core): make image_generate opt-in with one experimental config field Oct 29, 2026

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new commits look good. image_generate accepts true, {} or { model }, and both the opt-in check and the default model are read from the newest config document that sets it. The removed image_model handling leaves nothing behind in the repo. I checked it with the image-generate and config-normalisation tests (57 pass, covering each form, invalid values, the tool appearing and disappearing as the config changes, and the model fallbacks) and typecheck:tsc in packages/core and packages/schema. I couldn't run it end to end because the simulated provider has no image model.

Public API (config schema, OpenAPI spec, generated client types):

  • experimental.image_generate: boolean → boolean | { model?: "providerID/modelID[#variant]" | { providerID, model, variant? } }, defaults to off.
  • experimental.image_model: removed. It was added in #59939 and doesn't appear to be in a release yet. Any config that already uses it needs to move to image_generate: { model }.
  • The tool is now off unless image_generate is set.

No blocking concerns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant