Conversation
Images are first-class workspace resources: paste/drop/slash upload to workspace/assets/, Markdown holds rel paths, endpoints get [image: alt] text while harnesses read files via workspace scope. Adds MarginImage node (source-above, caption=title), slash menu (Floating UI), bubble link editor, Cmd/Ctrl+click link policy, media API + tests.
Images stay plain Markdown backed by workspace/assets/ (Obsidian-style
|WxH dims, {align=} trailer, Markdown as source of truth). Minimal
selected-state chrome: drag handles, reset, alignment, editable source.
Streamed uploads, vitest round-trip suite, docs/images.md.
Images section now lives in writing-guide.md (syntax table, paste/drag, no size limit, debugging pointer). Remove /images route; sidebar links Images to /writing-guide#images first in the Configuration group. Move debugging.md out of Configuration to top level.
Type /image at a block start to upload from the device (Downloads, etc.) via the OS file dialog. Files reuse the existing upload-to-assets pipeline with a file-switch guard; pasted URLs already import, so no URL mode. ITEMS registry is extensible for future entries. Minimal title+subtitle menu styling.
- ImageProvider protocol: Margin owns prompt/style/storage, providers own HTTP - OpenAI-compatible (generations + edits), Stability, FAL, and ComfyUI dual-slot (text/edit workflows, upload+inject reference, per-slot seed maps) - assets/generated/ opaque storage via save_generated_bytes, existing media serving - POST /api/images/generate (400 config / 502 upstream), /comfy/analyze, /logs, /reveal; POST /api/settings/test-image-provider with per-slot status - 400 = Margin config/request wrong, 502 = provider communication failure - Full pytest coverage: storage, validation matrix, routing, immutability
…nerate - Shared ImageGenerateDialog (prompt + style + reference thumbnail, abortable, file-switch guard drops cross-document inserts) - Slash menu gains Generate image; BubbleMenu gains Generate (selection becomes the initial prompt, never deleted; insert after selection) - Image toolbar gains Regenerate: src-only swap preserves size/align/caption, native undo restores the previous asset - Fresh generations use a fixed 'generated image' alt; regen prefills from the edit workflow's saved prompt text - generateImage client in lib/media; slash registry extracted to slashItems
- Settings Images tab: provider config + test, default/custom styles, per-slot ComfyUI workflow import with ranked prompt/image/seed pickers - History dropdown gains Chats/Images toggle (fixed width, minimal rows); full run details (input/output, submitted prompt, seed, paths) move to an ImageDetailPopup with copy-prompt and open-folder actions
- New GeminiProvider (Nano Banana family): text-to-image plus single reference-image edit, x-goog-api-key auth, fixed googleapis endpoint. Google's OpenAI-compat layer has no images route (404, probed live), so no code is shared with OpenAICompatibleProvider beyond the generate() contract and byte validation. - Defensive response parsing: documented output_image block first, magic-byte-validated recursive scan as fallback for envelope drift. - Safety refusals surfaced explicitly; auth failures map to 400, upstream/safety failures to 502 per the status table. - check_model() powers the Settings Test button (GET /v1beta/models). - Settings Images tab lists Gemini with key+model fields only. - 11 new tests: request shapes, nested-block fallback, auth/safety mapping, check_model, end-to-end path with null seed
- Log entries get stable ids at save time; DELETE /api/images/logs/{id}
removes one entry (legacy id-less entries match timestamp+path)
- History Images tab gains hover-reveal delete per row (mirrors chats),
closing the detail popup if its entry was deleted
- Image log fetches share one in-flight request so rapid open/tab-switch
sequences never fire redundant requests
- New image_style_overrides setting; resolution precedence is custom styles, then built-in overrides, then shipped defaults (None is hard-guarded to always mean no style) - list_styles returns effective prompt plus default_prompt and an overridden flag - Settings Images tab merges default/custom sections into one Styles list: every style shows name and prompt with default radio, inline edit, per-style reset for overridden built-ins, delete for customs
The bubble never unmounts, so a dismissed rewrite session stayed stuck and reshown on the next selection. Bind the session to its selection range and fall back to the default bubble when it clears or moves.
…friendly captions
…agine, pencil Imagine-again Bubble menu is now two space-separated pills: formatting (Paragraph, B/I/U, link, overflow) and AI (Cue, Rewrite, Imagine) with brand icons, dividers, and no hover titles. Imagine morphs inline with an expandable prompt and on-demand style pill instead of a dialog; the image pill's pencil opens a required-input Imagine-again bar with the same structure. Centralized toast notifications replace window.alert across editor flows. Settings Images tab: provider/ComfyUI-workflows split, Gemini URL hidden, hairline style rows with icon actions, deletable built-ins (except None), Images moved above Context, Harness renamed. Backend requires non-empty prompts; dead regen fallback removed. Docs updated to match.
…d loading ring - Second-slot morph: rewrite/imagine/link inputs animate in place of the AI pill with per-entry origins; formatting pill hidden while prompting - Boundary-aware positioning via Floating UI shift/flip - Minimal borderless style pills with pinned chevron in bubble and Imagine-again bar; unified expanded footers; send hints dropped - Loading shimmer scoped to the active input pill, quieter sweep
…show - Send buttons use SimpleAssist's filled-pill treatment in the bubble's 5px radius; pinned chevron on minimal style pills - Morph animation plays on mode switches only (cleared on animationend) so select-to-show stays instant; stable shouldShow stops per-render BubbleMenu transactions - Uniform 4px pill padding; formatting hidden while prompting; loading ring scoped to the active input with a quieter sweep
- index.html: Imagine Images, Slash Commands, Inline AI Bubble cards - writing-guide: link click vs Cmd/Ctrl+Click follow; slash prefix filtering
- Toast previously console-only failures: harness accept/reject, file open/save, settings load/save, history fetch/delete, copy, folder picker, workspace file listing, harness list - Toaster restyle: top-right, flat surface with semantic dot, no tinted backgrounds
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.
What
Makes the editor feel editor-first, AI-second:
Bubble menu (
ui/src/components/Editor/WritingBubbleMenu.tsx)brandIcons.tsx), hairline separators, no hover titles, equal-height pillsImage pill (
MarginImage.tsx)Slash menu — diamond/upload brand icons, narrower minimal menu, concise hints, word-prefix two-tier filtering
Toasts — new
toastStore+Toasterreplace allwindow.alertin editor/file flowsSettings Images tab — provider/ComfyUI-workflows split, Gemini URL hidden, hairline style rows with icon actions, deletable built-ins (except None) with restore, Images above Context, Harness renamed
Backend —
POST /api/images/generatenow always requires a prompt; removed the empty-prompt fallback + dead dialog regen branchDocs — writing-guide, debugging, ai-assist updated to the new vocabulary
Verification
npx tsc -b: cleanpytest: 113 passedvitestcould not run here (repo toolchain needs Node 22+, env has Node 20) — worth anpm testin CI before merge