Add /generate slash command for FLUX-1-schnell image generation#42
Merged
jonnyparris merged 2 commits intomainfrom Apr 23, 2026
Merged
Add /generate slash command for FLUX-1-schnell image generation#42jonnyparris merged 2 commits intomainfrom
jonnyparris merged 2 commits intomainfrom
Conversation
…e generation Wire up Workers AI image generation in Dodo via a new /generate slash command. Users can type /generate <prompt> to get a FLUX-1-schnell image rendered inline in the chat. Changes: - Add AI binding to wrangler.jsonc - Add AI: Ai to Env interface - Add @cf/black-forest-labs/flux-1-schnell to WORKERS_AI_MODELS catalog - Add POST /session/:id/generate endpoint (rate-limited 30/hr) - Add handleGenerate() in CodingAgent: persists user+assistant messages, calls env.AI.run() for FLUX, uploads base64 JPEG to R2, emits SSE message_attachments event for inline rendering - Add /generate slash command detection in dodo-chat.js client
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
dodo | fcb8ac1 | Apr 23 2026, 09:26 PM |
Apply all review comments from PR #42: Critical fixes: - C1: Guard against concurrent prompt collision (return 409 when another prompt is running, matching handleMessage's behaviour) - C2: Fall back to inline data URL when R2 is unavailable instead of silently emitting a text-only stub — users always see the image - C3: Enforce 2048-char prompt limit (FLUX-1-schnell schema cap) via a dedicated generateImageSchema Correctness: - Defensive FLUX response parsing (no more 'as { image: string }' type assertion) — throws a descriptive error if shape drifts - Random seed on every call so repeat prompts don't collapse to the same image - Split chat models (WORKERS_AI_MODELS) from image models (WORKERS_AI_IMAGE_MODELS) so FLUX never shows up in the chat model picker where it would brick every subsequent prompt - Centralize FLUX constants (model id, media type, max prompt length) UX: - Shorter assistant caption (truncate prompt to 80 chars + truncation marker) — long prompts no longer dominate the bubble - Multi-line prompt support in slash command regex ([\s\S]+ instead of .+) Cost/abuse: - Add daily cap (100/day) on top of hourly cap (30/hr) — bounds long-horizon FLUX cost exposure per user Refactor: - Extract persistGenerateUserMessage() and persistGeneratedImageMessage() helpers to keep handleGenerate readable (~70 lines instead of 140) Tests: - New test/generate-unit.test.ts covers slash command regex (basic, case-insensitive, multi-line, whitespace-only, concatenated, mid-message), FLUX prompt-length constant parity with the Workers AI schema, and the chat-vs-image model catalog separation - All 395 tests pass (up from 382)
2 tasks
jonnyparris
added a commit
that referenced
this pull request
Apr 23, 2026
#44) Follow-up to #42. Three things: 1. Slash command autocomplete in the chat input. Type '/' to see a menu of available commands (currently just /generate). Arrow keys + Enter/Tab complete, Escape dismisses. Menu positioned above the input, styled to match the rest of the app. 2. Server-side /generate routing. handleMessage and handlePrompt now detect /generate in the content and delegate to the image-generation core (runImageGeneration). This means /generate works from: - Browser UI (client intercept + this server fallback) - MCP send_message / send_prompt tools - Any future HTTP clients Previously the slash command only worked in the browser because the client JS was the only layer that knew about it. 3. New MCP tool: generate_image. Calls /generate directly with a prompt string. Lets LLM agents (incl. myself) invoke FLUX from conversations. Refactor: - Extract runImageGeneration() core from handleGenerate — shared entry point for the dedicated endpoint and slash-routed messages. - GENERATE_SLASH_REGEX + extractGeneratePrompt() in shared-index so the browser and server agree on what counts as a /generate request. Tests: - 6 new unit tests for extractGeneratePrompt (happy path, null on non-/ messages, whitespace handling, multi-line, case-insensitive) - Updated existing slash-regex tests to use the canonical shared export - All 401 tests pass
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/generate <prompt>slash command that generates images via Workers AI FLUX-1-schnell and renders them inlinePOST /session/:id/generateendpoint bypasses the LLM chat path entirelyattachments/and delivered via existingmessage_attachmentsSSE eventWhy
A previous session (
65c3019e) showed me asking an LLM (GPT-5.4) to generate a steampunk Cloudflare logo — it just offered prompt-writing advice instead. Dodo couldn't actually make images.Workers AI has FLUX-1-schnell available as
@cf/black-forest-labs/flux-1-schnelland the UI already knows how to render attachments. This PR wires the two together.What changed
wrangler.jsonc— addai: { binding: "AI" }src/types.ts— addAI: Aito theEnvinterfacesrc/shared-index.ts— add FLUX-1-schnell toWORKERS_AI_MODELScatalogsrc/index.ts— addPOST /session/:id/generate(rate-limited 30/hr per user)src/coding-agent.ts— addhandleGenerate():env.AI.run("@cf/black-forest-labs/flux-1-schnell", { prompt })uploadAttachment()message+message_attachmentsSSE eventspublic/js/dodo-chat.js— detect/generate <prompt>insendMessage()and route to new endpointTest plan
npx tsc --noEmitpassesnpx vitest run— all 382 tests pass/generate a cyberpunk catin a Dodo session, verify image renders inlineNotes
response.image— we upload that to R2 directly rather than inlining the data URLbeep-boop-🤖