* fix: reduce CPU usage during large XML streaming
Skip Prism syntax highlighting while tool call is streaming — use plain
<pre> during streaming and only run Prism once at completion. Also throttle
scrollIntoView to once per 150ms to avoid layout thrashing.
Profiled with Playwright + CDP: for 200-cell diagrams the longest
browser task dropped from 6.7s to ~450ms and total long-task time
fell from ~10.9s to ~1.1s.
* fix: add trailing edge to scroll throttle
Ensures the chat scrolls to the bottom after streaming ends, even if
the last messages update arrives during the 150ms throttle window.
Remove pinned v29.3.5 tag so the build always clones the latest draw.io.
This adds the Animated GIF export and other new features to the Electron app.
Closes#770
All three POST handlers (/api/state, /api/restore, /api/history-svg)
now use a shared readBody() helper that enforces a 10MB limit and
returns 413 if exceeded, preventing memory exhaustion from oversized
requests.
Bumps @next-ai-drawio/mcp-server to 0.1.19.
The embedded HTTP sidecar was using server.listen(port) without a host
argument, which defaults to 0.0.0.0 (all interfaces). This exposed the
server to the local network. Now explicitly binds to 127.0.0.1.
Also excludes release/ from tsconfig to fix pre-existing TS errors.
Bumps @next-ai-drawio/mcp-server to 0.1.18.
- Fix zoom resetting when dragging items (#775): removed useEffect that
called load() on every autosave-triggered chartXML change, which reset
the viewport. Moved diagram restore logic to onDrawioLoad where it
only fires on remount.
- Fix IndexedDB VersionError: template-storage.ts shared the same DB
name as session-storage.ts but at version 2, causing session storage
to fail with "requested version (1) < existing version (2)". Give
templates their own DB ("next-ai-drawio-templates").
Replace wildcard `Access-Control-Allow-Origin: *` with same-origin check,
preventing external websites from accessing MCP server APIs via cross-origin requests.
The npm audit check was failing due to vulnerabilities in transitive
dependencies (e.g. wrangler), blocking unrelated PRs.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace newyear-referral URL with new Coding Plan referral URL across all files
- Update model name from K2-thinking to glm-4.7
- Add volcengine invite poster to Chinese README and about page
Use explicit from/to/filter file sets instead of top-level globs to
avoid a regression in electron-builder 26.8.x where dist-electron
files were not being included in the asar archive.
electron-builder 26.8.x no longer auto-includes package.json when a
custom files array is specified, causing the main entry file to not be
found in the asar archive.
* feat: add custom system message setting for AI personalization
Allow users to enter custom instructions via a textarea in Settings
that get appended to the AI's system prompt. Includes server-side
validation (type check + 5000 char limit), localStorage persistence,
and i18n support for all 4 locales.
* fix: add accessibility htmlFor/id pairing on custom system message textarea
* feat: add Material Design Icons shape library (#685)
Add Google Material Design Icons as a new shape library using Google's
CDN. Includes top 300 most popular icons by usage, and updates system
prompts to guide the AI to call get_shape_library before using any icon
library.
* fix: align get_shape_library guidance for non-cloud icon libraries
* feat: add PNG/SVG export support to MCP server export_diagram tool
Previously export_diagram only supported .drawio XML files. This adds
PNG and SVG export by leveraging the existing browser sync mechanism:
the MCP tool sets an exportFormat flag on the session state, the browser
detects it via polling and triggers an iframe export, then POSTs the
result back as exportData which the tool reads and writes to disk.
* fix: address PR review feedback for export feature
- Validate exportData is a string in POST /api/state
- Update lastUpdated in setExportFormat to prevent session expiry
- Gate export postMessage on isReady to avoid lost messages
- Remove unused fmt variable
- Fix double extension when path has a different supported extension
* fix: resolve high severity npm audit vulnerabilities
Run npm audit fix to update @aws-sdk and @smithy transitive dependencies
that had high severity advisories, which was failing the CI security audit step.
* fix: address second round of PR review feedback
- Add 8s timeout for pendingMcpExport to prevent permanent blocking
- Move export trigger after version update in poll() to export latest diagram
- Return 404 when session not found for exportData POST
- Sync browser state before .drawio export to avoid stale XML
- Handle URL-encoded SVG data URIs in addition to base64
* fix: address third round of PR review feedback
- Sync browser state before PNG/SVG export (not just drawio)
- Add 10MB body size limit on POST /api/state
- Validate export response format matches request to prevent race conditions
* refactor: remove over-engineered defensive code from export feature
Strip unnecessary validation/guards added from Copilot review that
don't make sense for a localhost-only MCP server: body size limit,
type validation, 404 for missing session, lastUpdated refresh,
URL-encoded SVG handling. Also deduplicate requestSync call.
* refactor: keep original drawio export path unchanged
Don't restructure the existing drawio logic - just add png/svg
as a separate branch after it.
* refactor: remove redundant helper functions, inline state access
Remove setExportFormat/getExportData/clearExportData wrappers that
were each called once. Access state fields directly via getState().
* chore: bump mcp-server version to 0.1.16
Support multiple API keys per provider with random selection for load
balancing. When AI_MODELS_CONFIG has multiple apiKeyEnv values for
a provider, requests will randomly select one available key.
- Update schema to accept apiKeyEnv as string or string array
- Add random key selection in resolveApiKey()
- Update validation to check at least one key exists
- Add tests for array format support
* fix: enable image support for Kimi K2.5 model
Kimi K2.5 supports image input but was incorrectly blocked by the
supportsImageInput check that excluded all Kimi models without
"vision" in the name. Updated the condition to only exclude the
older K2 model while allowing K2.5.
* fix: improve Kimi K2.5 image support logic and add tests
- Only block kimi-k2 specifically, not all Kimi models
- Add unit test for kimi-k2.5 image support
This reverts commit e7c29fb410.
The PR introduced an IndexedDB error: 'Failed to execute transaction on IDBDatabase: The database connection is closing.'
* fix(electron): prevent beforeunload prompt by using autosave
- Enable draw.io autosave and handle autosave events to update chartXML
- Clear modified state after autosave to avoid beforeunload prompts
- Disable confirmExit in draw.io configuration
- Set modified=false and keepmodified=false URL parameters
- Fix session save condition to also save when only diagram exists
* fix: persist diagram-only saves and ref typing
* fix: harden persistence checks and export timeout
* feat(electron): bundle draw.io for offline support
- Download draw.io static files during CI build (v29.3.5)
- Detect Electron and use local draw.io files instead of CDN
- Add offline=1 parameter to disable external service calls
- Skip /drawio path from i18n middleware redirect
- Add public/drawio/ to .gitignore (downloaded during build)
This allows the Electron app to work completely offline.
* chore: bump version to 0.4.12-beta.3 for offline test
* fix(electron): ad-hoc sign macOS app for bundled draw.io compatibility
* chore: bump version to 0.4.12-beta.4 for ad-hoc sign test
* fix(electron): disable electron-builder signing to use custom ad-hoc signing
* chore: bump version to 0.4.12-beta.5
* feat(mcp): update UI with project logo and modern dialog styles
- Replace Next.js logo with project favicon-white.svg
- Modernize modal dialogs with backdrop blur, animations, and DM Sans font
- Update button styles to match header design
- Change title to "Next AI Draw.io"
- Rename "Save" to "Download" for clarity
- Bump version to 0.1.15
* chore: remove dead code (unused download helpers and pendingManualSave)
Fixes#633 - browser showing infinite loading spinner when accessing
the MCP server URL without the session parameter.
When users access http://localhost:6002 directly (without ?mcp=xxx),
the page now auto-redirects to the most recent active session instead
of showing "No session" with an infinite loading spinner.
Upgrade wrangler from 4.58.0 to ^4.60.0 to fix the command injection
vulnerability (CWE-78) in the --commit-hash parameter of wrangler pages
deploy command.
Fixes#627
* fix(quota): bypass quota for users with Bedrock credentials
The hasOwnApiKey check only looked for x-ai-api-key header, but Bedrock
users provide AWS credentials via x-aws-access-key-id instead. This
caused Bedrock users with their own credentials to still be subject to
quota limits.
* fix(quota): also bypass quota for Vertex AI users
* style: auto-format with Biome
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
cpSync with dereference:true does NOT convert symlinks to files.
This implements a custom copyDereferenced function that:
- Detects symlinks using lstatSync
- Follows them using statSync
- Copies actual file/directory content instead of symlink
Fixes macOS arm64 codesign failure with electron-builder 26.4.0
which now does ad-hoc signing and runs codesign --verify.
* fix: allow private URLs by default for reverse proxy setups
Fixes#588 - Users with reverse proxy setups (e.g., Antigravity tools)
were getting "Invalid base URL" errors due to SSRF protection blocking
private/internal URLs.
Changes:
- Add ALLOW_PRIVATE_URLS env var (defaults to true)
- Set to "false" to enable strict SSRF protection if needed
* refactor: extract isPrivateUrl to shared utility
After create_new_diagram, edit_diagram would fail with "You must call
get_diagram first" because lastGetDiagramTime was never set (remained 0
from session init). This fix sets lastGetDiagramTime after creating a
diagram, allowing immediate edits.
Fixes#534, Fixes#589
- Add missing "Problem" statement to FAQ #4 for consistency
- Update vision model recommendations to latest versions (GPT-5.2, Claude 4.5 Sonnet, Gemini 3 Pro)
- Add FAQ.md in English, Chinese, and Japanese
- Link FAQ from each language README
- Cover: PDF export, offline deployment, self-hosted models, image upload
SiliconFlow is transitioning from .com to .cn domain. The .cn endpoint
uses Global Traffic Manager (GTM) for better global access, while .com
is being phased out.
Add separate plugin package for Claude Code plugin directory submission.
Structure:
- .claude-plugin/plugin.json - plugin metadata
- .mcp.json - MCP server configuration
- README.md - documentation with use case examples
- Split workflow into mac/linux and windows jobs
- Add dist:win:build script with --publish never
- Integrate SignPath signing for Windows executables
- Sign both NSIS installer and portable EXE files
DeepSeek provider was not properly formatting image content for Doubao's
API. Now uses OpenAI provider for Doubao models (multimodal support),
while keeping DeepSeek provider for DeepSeek/Kimi models on the platform.
Dockerfile was missing the ARG declaration to receive NEXT_PUBLIC_BASE_PATH
from docker-compose build args, causing subdirectory deployment to fail.
Fixes#478
* test: add Vitest and Playwright testing infrastructure
- Add Vitest for unit tests (39 tests)
- cached-responses.test.ts
- ai-providers.test.ts
- chat-helpers.test.ts
- utils.test.ts
- Add Playwright for E2E tests (3 smoke tests)
- Homepage load
- Japanese locale
- Settings dialog
- Add CI workflow (.github/workflows/test.yml)
- Add vitest.config.mts and playwright.config.ts
- Update .gitignore for test artifacts
* test: add more E2E tests for UI components
- Chat panel tests (interactive elements, iframe)
- Settings tests (dark mode, language, draw.io theme)
- Save dialog tests (buttons exist)
- History dialog tests
- Model config tests
- Keyboard interaction tests
- Upload area tests
Total: 15 E2E tests, all passing
* test: fix E2E test issues from review
Fixes based on Gemini and Codex review:
- Remove brittle nth(1) selector in keyboard tests
- Remove waitForTimeout(500) race condition
- Remove if(isVisible) silent skip patterns
- Add proper assertions instead of no-op checks
- Remove expect(count >= 0) that always passes
- Remove unused hasProviderUI variable
All 14 E2E tests and 39 unit tests pass.
* style: auto-format with Biome
* fix: resolve lint errors for CI
* test(e2e): add diagram generation tests with mocked AI responses
- Add tests for generate, edit, and append diagram operations
- Use SSE mocked responses matching AI SDK UI message stream format
- Generate mxCell XML directly in tests for deterministic assertions
- Tests verify tool card rendering and 'Complete' badge state
* test: add comprehensive E2E tests for all major features
- Error handling tests (API errors, rate limits, network timeout, truncated XML)
- Multi-turn conversation tests (sequential requests, history preservation)
- File upload tests (upload button, file preview, sending with message)
- Theme switching tests (dark mode toggle, persistence, system preference)
- Language switching tests (EN/JA/ZH, persistence, locale URLs)
- Iframe interaction tests (draw.io loading, toolbar, diagram rendering)
- Copy/paste tests (chat input, XML input, special characters)
- History restore tests (new chat, persistence, browser navigation)
* refactor: extract shared test helpers and improve error assertions
- Create tests/e2e/lib/helpers.ts with shared SSE mock functions
- Add proper error UI assertions to error-handling.spec.ts
- Remove waitForTimeout calls in favor of real assertions
- Update 6 test files to use shared helpers
* docs: add testing section to CONTRIBUTING.md
* fix: improve test infrastructure based on PR review
- Fix double build in CI: remove redundant build from playwright webServer
- Export chat helpers from shared module for proper unit testing
- Replace waitForTimeout with explicit waits in E2E tests
- Add data-testid attributes to settings and new chat buttons
- Add list reporter for CI to show failures in logs
- Add Playwright browser caching to speed up CI
- Add vitest coverage configuration
- Fix conditional test assertions to use test.skip() instead of silent pass
- Remove unused variables flagged by linter
* fix: improve E2E test assertions and remove silent skips
- Replace silent test.skip() with explicit conditional skips
- Add actual persistence assertion after page reload
- Use data-testid selector for new chat button test
* refactor: add shared fixtures and test.step() patterns
- Add tests/e2e/lib/fixtures.ts with shared test helpers
- Add tests/e2e/fixtures/diagrams.ts with XML test data
- Add expectBeforeAndAfterReload() helper for persistence tests
- Add test.step() for better test reporting in complex tests
- Consolidate mock helpers into fixtures module
- Reduce code duplication across 17 test files
* fix: make persistence tests more reliable
- Remove expectBeforeAndAfterReload from mocked API tests
- Add explicit test.step() for before/after reload checks
- Add retry config for flaky clipboard tests
- Add sleep after reload for language persistence test
* test: remove flaky XML paste test
* docs: run both unit and e2e tests before PR
* chore: add type check and unit test git hooks
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
PR #442 accidentally changed showSaveDialog from using the diagram
context to local state, breaking draw.io's native save button (Ctrl+S)
that was fixed in PR #296.
This restores the original behavior by using the context's showSaveDialog
so both draw.io native save and the download button open the same dialog.
* feat(session): add chat session history with IndexedDB storage
- Add session-storage.ts with IndexedDB wrapper using idb library
- Add use-session-manager.ts hook for session state management
- Add session-history-dropdown.tsx for session selection UI
- Integrate session system into chat-panel.tsx
- Auto-generate session titles from first user message
- Auto-save sessions on message completion
- Support session switching, deletion, and creation
- Migrate existing localStorage data to IndexedDB
- Add i18n translations for session history UI
* feat(session): improve history dropdown and persist diagram history
- Add time-based grouping (Today, Yesterday, This Week, Earlier)
- Add thumbnail previews using Next.js Image component
- Add staggered entrance animations with fade-in effects
- Improve active session indicator with left border accent
- Fix scrolling by using native overflow instead of ScrollArea
- Persist diagram version history to IndexedDB sessions
- Remove redundant diagram XML from localStorage
- Add i18n strings for time group labels (en, ja, zh)
* fix(session): prevent data loss on theme change and tab close
- Add isDrawioReady effect to restore diagram after DrawIO remount
- Add visibilitychange handler to save session when page becomes hidden
- Fix missing currentSessionId in saveCurrentSession dependency array
- Remove unused sanitizeMessages import from use-session-manager
* fix(session): fix diagram save and migration data loss bugs
- Add diagramHistory to save effect dependency array so diagram-only
edits trigger saves (previously only message changes did)
- Destructure stable sessionManager values to prevent unnecessary
effect re-runs on every render
- Add try-catch wrapper around debounced async save operation
- Make saveSession() return boolean to indicate success/failure
- Verify IndexedDB write succeeded before deleting localStorage data
during migration (prevents data loss if write silently fails)
- Keep localStorage data for retry if migration fails instead of
marking as complete anyway
* refactor(session): extract helpers to reduce code duplication
- Add syncUIWithSession helper to consolidate 4 duplicate UI sync blocks
- Add buildSessionData helper to consolidate 4 duplicate save logic blocks
- Remove unused saveTimeoutRef and its cleanup effect
- Net reduction of ~80 lines of duplicate code
* style(ui): improve history dropdown and delete dialog styling
- Change destructive color from coral to muted rose for refined look
- Make session history panel taller (400px fixed height)
- Fix popover alignment to prevent truncation
- Style delete button with soft red outline instead of solid fill
- Make delete dialog more compact (max-w-sm)
* fix(session): reset refs on new chat and show recent sessions
- Fix cached example diagrams not displaying after creating new session
- Reset previousXML, lastProcessedXmlRef and processedToolCalls when
messages become empty (new chat or session switch)
- Add recent chats section in empty chat state with collapsible examples
- Pass sessions and onSelectSession to ChatMessageDisplay
- Add loadedMessageIdsRef to skip animations on session restore
- Add debug console.log for diagram processing flow
* feat(session): add search bar and improve history UI
- Remove session history dropdown, use main panel instead
- Add search bar to filter history chats by title
- Show minutes (Xm ago) instead of "Just now" for recent sessions
- Scroll to top when switching to new/empty chat
- Remove title truncation limit for better searchability
- Remove debug console.log statements
* refactor: remove redundant code and fix nested button hydration error
- Remove unused 'sessions' from deleteSession dependency array
- Remove unused 'switchedTo' variable and simplify return type
- Remove unused 'restoredMessageIdsRef' (always empty)
- Fix nested button hydration error by using div with role=button
- Simplify handleDeleteSession callback
* fix(session): fix migration bug, improve metadata perf, truncate titles
- Fix migration retry loop when localStorage has empty array
- Use cursor-based iteration for getAllSessionMetadata
- Truncate session titles to 100 chars with ellipsis
* refactor: remove dead code and extract diagram length constant
- Remove unused exports: getAllSessions, createNewSession, updateSessionTitle
- Remove write-only CURRENT_SESSION_KEY and all localStorage calls
- Remove dead messagesEndRef and unused scroll effect
- Extract magic number 300 to MIN_REAL_DIAGRAM_LENGTH constant
- Add isRealDiagram() helper function for semantic clarity
* fix: faster message restore and skip panel animation on refresh
- Use useLayoutEffect for localStorage restore (runs before paint)
- Track visibility changes to only animate panel when toggling, not on page load
- Use cn() utility for cleaner conditional className
* fix: reset animation state after completion for re-animation support
* revert: remove unnecessary animation reset timer
- Add isRestored state to track when localStorage restoration completes
- Show example panel only after confirming no saved messages exist
- Skip message animations for restored messages
- Default tool calls and reasoning blocks to collapsed for restored messages
- Update biome schema version from 2.3.8 to 2.3.10
- Add radix parameter to parseInt in mcp-server
- Remove unnecessary React fragment in model-config-dialog
- Fix unused variable errors (err -> _err)
- Auto-format code with biome
* fix(mcp-server): add graceful shutdown to prevent zombie processes
Add lifecycle handlers to properly exit the MCP server when the parent
application closes:
- Listen for stdin close/end events (primary method for all platforms)
- Handle SIGINT/SIGTERM signals
- Handle stdout broken pipe errors
- Export shutdown() function from http-server to clean up resources
* chore(mcp-server): bump version to 0.1.11
Some models (Kimi K2, DeepSeek, Qwen text models) don't support image/vision
input. The AI SDK silently drops unsupported image parts, causing confusing
responses where the model acts as if no image was uploaded.
Added supportsImageInput() function to detect unsupported models by name,
and return a 400 error with clear guidance when users try to upload images
to these models.
Closes#469
* docs: reorganize docs into en/cn/ja folders
- Move documentation files into language-specific folders (en, cn, ja)
- Add Chinese and Japanese translations for all docs
- Extract Docker section from README to separate doc file
- Update README to link to new doc locations
* docs: fix links to new docs folder structure
* docs: update README and provider docs
* docs: fix broken import statements in cloudflare deploy guides
* docs: sync CN/JA READMEs with EN structure and fix all paths
- Remove About link and sponsor notice icon from chat panel header
- Remove language switcher (English | 中文 | 日本語) from all about pages
- Fix About link in settings dialog to use current language
- Remove unused sponsorTooltip translation key from all dictionaries