Nightly Build / build (push) Successful in 5m42s
image_generate wrote the file into the server's own data/images/ and handed
that host path to the model. It is a path in nobody's vocabulary: not the
caller's home, not their container. Telegram's send_attachment therefore
resolved it under the user's home and answered "file not found", and
read_file, execute_cmd and the viewer could not reach it either. The web URL
was the only surface that worked, which is why the failure only ever showed
on Telegram -- and why the model there, having no working way to hand the
file over, started inventing send_photo and send_media.
Placement moves to the tool, the one place holding a ToolContext:
- The manager returns bytes (generate_bytes) and no longer knows where an
image goes. It has no UserFs and no session, so it never could have.
- run_with saves through uploads::save_to_home into uploads/{session}/. The
returned path is agent vocabulary, so every consumer resolves it, and that
is the one directory the media inliner is authorized to read from -- a
vision model can be shown the image it just made. execute_async, the
context-free path, now fails loudly rather than writing somewhere nobody
can read; same shape as execute_cmd.
- The extension is sniffed rather than assumed png: it is what decides
whether Telegram sends the picture inline or as an anonymous document, and
providers return jpeg and webp too. The file is named after the prompt, so
it reads as something in the explorer and in Telegram.
The result still carries a url, since the chat renders Markdown images and
 beats naming a file the user then has to open. It points at
/api/file?path=..., which resolves through the caller's own UserFs. The old
/api/images/{id} route is removed: it had no writer left once placement
moved, and it addressed one instance-wide directory behind require_auth
alone, with no notion of who owned the image -- the same shape as the /data
static mount removed before it. That leaves data_root unused, so the manager
no longer knows about the server's filesystem at all.
Docs: the Telegram page explains send_attachment as the channel's equivalent
of show_file_to_user; the ComfyUI page says where a generated image lands and
which of the two handles to use where.
Also introduces CHANGELOG.md and the standing rule for it in CLAUDE.md.
33 lines
2.9 KiB
Markdown
33 lines
2.9 KiB
Markdown
# ComfyUI
|
|
|
|
- **Plugin id:** `comfyui`
|
|
- **Category:** Image generation, local
|
|
- **Runs:** talks to a separately-running ComfyUI server over HTTP (default `http://localhost:8188`)
|
|
|
|
## What it does
|
|
|
|
Turns a locally running [ComfyUI](https://github.com/comfyanonymous/ComfyUI) installation into one or more image-generation models the assistant can call. Every JSON workflow file dropped into a watched folder becomes its own selectable model — so a user can have separate "photo-realistic", "anime", "upscale" etc. workflows, each showing up independently.
|
|
|
|
The plugin polls the ComfyUI server every 5 seconds. If it's offline, every model built from it disappears until it comes back; if a workflow file is added, edited, or removed, the model list updates live — no restart needed.
|
|
|
|
## Requirements
|
|
|
|
- ComfyUI installed and running somewhere reachable from this machine (its own GPU-heavy install, not something this app manages).
|
|
- At least one workflow exported from ComfyUI as a JSON API file, containing a `CLIPTextEncode` node (for text-to-image) and/or an image-loading node (for image-to-image). Advanced workflows can add a `_personal_agent` metadata block inside the JSON to control exactly which node/field receives the prompt, negative prompt, width/height/steps, and input image — without that block the plugin auto-detects the first `CLIPTextEncode` node.
|
|
|
|
## Enabling & configuring (admin)
|
|
|
|
1. Plugins page → **ComfyUI** → enable, then **Configure**.
|
|
2. Fields:
|
|
- **`base_url`** (default `http://localhost:8188`) — where ComfyUI's API is listening.
|
|
- **`workflows_dir`** (default `data/comfyui/workflows`) — folder to watch for `.json` workflow files. Created automatically if missing.
|
|
- **`default_negative`** — an optional negative prompt applied to every workflow that has a negative-prompt node.
|
|
3. Put workflow JSON files in the workflows folder. Each becomes a model named after the file (or the `name` given in its `_personal_agent` block) in the **Image generation** section of the Models hub — no separate "add provider" step, since this plugin registers its models directly.
|
|
|
|
## Notes
|
|
|
|
- A single generation can take up to 5 minutes before the plugin times out and reports an error.
|
|
- Image-to-image is supported when the workflow declares an `input_image_node` in `_personal_agent`.
|
|
- A generated image is saved into the requesting user's own workspace, under `uploads/<conversation id>/`, and the tool returns both a path and a web URL. In the web or mobile chat, embedding the URL as a Markdown image shows the picture directly in the conversation; the path is for everything else — `show_file_to_user`, `send_attachment` on Telegram (which has no Markdown, so the file must be sent, not linked), and ordinary file work like reading it, moving it into a project or a shared folder, or processing it with a command.
|
|
- If ComfyUI is unreachable, tell the user to start their ComfyUI server — there is nothing to fix in this app's configuration in that case.
|