Skip to content

Releases: GooDAnDReaDY/dsh-image-gen

dsh-fal-image-gen 0.7.0

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 23 Aug 11:44

Two providers that need no key at all: codex draws with gpt-image-2 and grok with grok-imagine, both through a subscription you are already logged into.

Nothing about keys, logins or token refreshing lives in this plugin. The subscriptions plugin owns the account and lends a finished picture through an in-process service — the token never crosses, and there is still exactly one owner of the refresh. Without that plugin the two providers decline with a sentence saying so, and the rest of the plugin is unaffected.

The named sizes stay the tool's language and map onto the subscription's own sizes; Grok's aspect ratios follow from those. subscriptionQuality passes low, medium or high when the subscription accepts one.

dsh plugin --profile web add @goodandready/dsh-fal-image-gen
dsh plugin --profile web add @goodandready/dsh-subscriptions

dsh-fal-image-gen 0.6.1

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 20 Aug 16:34

Settings now work when the Web UI is opened at a LAN address rather than localhost.

The harness turns its settings service off on any page that is not loopback: the settings document is never read, every namespace reports unavailable, and saving silently does nothing. That is a decision made in the browser — the server serves settings over the network perfectly well.

@goodandready/dsh-lanmode stands the same machinery up over the same calls. This release makes the card use it when it is installed, and the core service otherwise — which stays correct on a loopback page.

dsh plugin --profile web add @goodandready/dsh-lanmode

Nothing else changed.

dsh-fal-image-gen 0.6.0

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 20 Aug 12:24

The settings card moves out of Settings → Plugins → Plugin configuration and into its own section in the settings sidebar, next to Vision, Voice, Speech and Key Rotation.

Why

On some deployments that core tab renders empty — the plugins themselves load fine, there is no error banner, and a cache-bypassing reload does not help. The tab is drawn by the core and a plugin cannot reach into it. A plugin's own section is drawn by the plugin, so it does not depend on that tab at all.

The move also retires a compatibility workaround: the registration had to carry both id and key, because the slot changed shape between core versions. settings.section takes id on all of them.

Two details that came with it

  • the card started collapsed — sensible among many cards in a tab, but on a page of its own that reads as a blank page, so it now opens straight into the form;
  • when the namespace was not published yet the card returned nothing at all, leaving an unexplained empty section. It now says what is going on in one line.

Nothing about generation itself changed: the same providers, the same tool, the same settings.

Install

dsh plugin --profile web add @goodandready/dsh-fal-image-gen

dsh-fal-image-gen 0.5.1

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 20 Aug 10:33

The plugin's card was sometimes missing from Settings → Plugins → Plugin configuration entirely, and stayed missing until the page was reloaded.

Why

The browser keeps one mirror of the Host settings document, and every settings surface — this card and the core ones alike — derives from it. It refreshes on exactly two signals, a document commit and a (re)connect. A namespace registering is neither: settings.register adds the registration to the registry and never emits settings/document-updated, which only a value change or a commit does.

The Host, meanwhile, answers HTTP well before registration finishes — on one harness the port was announced 1.4 seconds after start. A page that reads settings.describe inside that window gets a view without the namespaces that have not registered yet, and then never re-reads it. Nothing in the tab can recover: the card is not mounted there, so it cannot fix itself the way a mounted component could.

What changed

The client half asks the mirror to re-read while its namespace is absent from it — once a second, at most fifteen times. The mirror is shared, so one re-read brings back every other card too, including the core ones. In the healthy case this costs nothing measurable: the first check sees the namespace and no timer is ever started.

Verified on a staging harness. With the namespace present the check is a no-op and the card renders as before. With registration disabled in the installed host copy, the retry ran for twenty seconds with zero page errors, the core cards stayed intact, and the card was correctly absent — the Host really does not have that namespace, and the plugin does not pretend otherwise.

The real fix belongs upstream: either open the port after registration finishes, or invalidate the mirror when a namespace registers.

Install

dsh plugin --profile web add @goodandready/dsh-fal-image-gen

dsh-fal-image-gen 0.5.0

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 20 Aug 09:19

The plugin was FAL from end to end. It is becoming the one image generation plugin, where FAL is a provider rather than the whole design.

Providers

A provider now turns a prompt into image bytes and nothing else. Everything after that — the attachment, the durable copy in the session workspace, the same-origin URL that outlives the provider's own link, the tool card — is shared and written once.

provider What it is Protocol
fal (default) the FAL queue, exactly as before submit, poll, download
custom any OpenAI-compatible API one POST {customBaseURL}/images/generations
- id: dsh-fal-image-gen
  config:
    provider: custom
    customBaseURL: https://api.openai.com/v1
    customModel: gpt-image-1
    customKeyEnv: OPENAI_API_KEY

All four fields are editable in the settings card. An empty customKeyEnv means no authorization header at all — a real case for a local gateway, not a misconfiguration.

Sizes stay the tool's language

The named sizes do not change when the provider does, so a prompt keeps its meaning. FAL takes them as they are; for an OpenAI-compatible API they are translated (landscape_4_31024x768). An API picky about sizes gets customSize, which is sent verbatim instead.

response_format is deliberately not sent: newer OpenAI models reject it, and the answer is read either way — base64 inline, or a link that is downloaded.

Removed: a settings field that lied

The card offered "Max images per call" (numImagesMax), but no such key existed in the host schema and generate_image has no num_images parameter — it always asks for one image. Turning the knob changed nothing.

Also

  • default outputDir moves from generated/fal to generated/images, since the folder is no longer FAL's; deployments that set it explicitly are unaffected;
  • 12 unit tests, the first this plugin has had.

Renaming to @goodandready/dsh-image-gen waits until the provider set settles.

Install

dsh plugin --profile web add @goodandready/dsh-fal-image-gen

dsh-fal-image-gen 0.4.1

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 20 Aug 07:12

Compatibility fix for dsh 0.1.0-rc.8.

On rc8 the whole client half of the plugin failed to apply:

keyed slot "settings.plugin.item" requires options.key

and both cards went with it — the settings section and the generate_image result card, so a generated picture arrived as a JSON dump again.

The slot changed shape between core versions: a list slot needing options.id up to rc7, a keyed slot needing options.key from rc8, where the tab asks the Host for the configurable namespaces and renders one card per namespace. Each check only looks at its own field, so the registration now carries both and one build works on either version.

Verified on a staging harness running rc8 with the full plugin set: reproducible before the change, gone after — zero failed to apply entries, container healthy.

Install

dsh plugin --profile web add @goodandready/dsh-fal-image-gen

dsh-fal-image-gen 0.4.0

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 19 Aug 20:07

Two delivery modes. The picture appears in the conversation either way; what changes is what the chat model receives.

link (new default) image
The model receives text and a link the image itself
Shown in the chat yes, the card renders it from the link yes
Works with a text-only chat model yes, on its own no — needs dsh-vision-bridge or a vision-capable model
The model can reason about the picture no yes

link is the default because it works in every deployment. Pick image when the conversation should be able to discuss what was drawn — "make the cat bluer" needs a model that can actually see it.

The tool description no longer claims the model can see the picture when it only got a link; without that line a model happily invents what it never saw. The link points at the plugin's own route rather than fal.media, which expires.

Also fixes settings, which never worked for this plugin. The host never registered its settings namespace and had no settings service injected, so the card bound to a namespace nobody declared, stayed unready and rendered nothing. The config is now read per call, so an edit applies to the next generation instead of after a restart.

Install

dsh plugin --profile web add @goodandready/dsh-fal-image-gen

dsh-fal-image-gen 0.3.0

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 19 Aug 18:37

Изображение теперь показывается прямо в чате.

  • Своя карточка результата. Карточки инструментов в dsh не рисуют image-блоки — это умеют только сообщения пользователя и ассистента, поэтому сгенерированная картинка приходила как путь плюс JSON-дамп вложения. Плагин регистрирует keyed-запись tool.call.toolview для generate_image и отдаёт байты своим роутом GET /dsh-fal-image-gen/image.
  • num_images убран. FAL генерировал и считал деньги за все картинки, а сохранялась и показывалась только первая.
  • Относительный outputDir теперь считается от рабочей папки сессии (exec.agent.session.header.cwd), а не от каталога, из которого запущен харнесс.
  • Scoped-имя сведено в трёх местах (package.json, bundle patch, id загрузчика клиента) — без этого браузерная половина не попадает в граф при установке из npm.

Проверено на живом профиле: картинка сгенерирована и показана в карточке, файл записан в папку сессии, роут отдаёт ровно те же байты (200, image/png, 512×512) и отбивает некорректный id (400).

Установка

dsh plugin --profile web add @goodandready/dsh-fal-image-gen