* Add success toast after saving diagram
* fix: correct save toast placement
* Changes made:
1. Added i18n support
2. Fixed the issue where the save toast was running only once
* fix: show toast after download completes, not when dialog opens
Move toast from handleDrawioSave (dialog open) to saveDiagramToFile
(after download). Also restore the duplicate-save guard that was removed.
---------
Co-authored-by: Biki Kalita <86558912+Biki-dev@users.noreply.github.com>
Co-authored-by: dayuan.jiang <jdy.toh@gmail.com>
* 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
- 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
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
- 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
* fix(edit_diagram): implement cascade delete for children and edges
- Add automatic cascade deletion when deleting a cell
- Recursively delete all child cells (parent attribute references)
- Delete all edges referencing deleted cells (source/target)
- Skip silently if cell already deleted (handles AI redundant ops)
- Update prompts to inform AI about cascade behavior
Fixes#450
* fix: add root cell protection and sync MCP server cascade delete
- Add protection for root cells '0' and '1' to prevent full diagram wipe
- Sync MCP server with main app's cascade delete logic
- Both lib/utils.ts and packages/mcp-server now have identical delete behavior
* chore(mcp): bump version to 0.1.9
* fix(cascade-delete): recursively collect edge children (labels)
- Change from cellsToDelete.add(edgeId) to collectDescendants(edgeId)
- Fixes orphaned edge labels causing draw.io to crash/clear canvas
- Edge labels (parent=edgeId) are now deleted with their parent edge
- Add 'Use Your API Key' button to open model config dialog
- Add ByteDance Doubao sponsorship message with registration link
- Update quota limit messages to be warmer and friendlier
- Add dev panel button to test quota toast
- Update i18n translations for EN, ZH, JA
* feat: add doubao provider and ByteDance sponsorship
- Add doubao provider using DeepSeek SDK with Volcengine base URL
- Add ByteDance Doubao sponsorship acknowledgment to about pages
- Update all README files (EN/CN/JA) with K2-thinking model info
- Update ai-providers.md with doubao configuration
- Keep both gateway and doubao providers after merge
* style: auto-format with Biome
* feat: add doubao and sglang to provider config panel
* fix: add doubao and sglang to validate-model API and logo maps
* docs: update ByteDance sponsorship note in all README versions
* docs: add Doubao logo to sponsorship note
* fix: use raw GitHub URL for Doubao logo in READMEs
* fix: separate link and image in sponsorship note
* fix: use PNG instead of SVG for Doubao logo
* fix: use current branch for PNG URL (will update to main after merge)
* docs: reorganize Deployment section and update image URLs to main
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* fix: move History and Download buttons to Settings dialog for cleaner chat interface
* fix: cleanup unused imports/props, add i18n for diagram style
* fix: use npx directly to avoid package-lock.json changes in CI
---------
Co-authored-by: dayuan.jiang <jdy.toh@gmail.com>
- Change from single key (PK only) to composite key (PK + SK)
- PK = user ID, SK = date for per-day history tracking
- Remove two-step daily reset logic (SK handles day separation)
- Rename dailyReqCount/dailyTokenCount to reqCount/tokenCount
- Remove TTL (data never expires per user request)
- Simplify checkAndIncrementRequest to single atomic update
- Fix recordTokenUsage to handle new items explicitly
New table: next-ai-drawio-quota-v2
* feat: add toggle to show unvalidated models in model selector
Add a toggle switch in the model configuration dialog to allow users to
display models that haven't been validated. This helps users who work with
model providers that have disabled their verification endpoints.
Changes:
- Add showUnvalidatedModels field to MultiModelConfig type
- Add setShowUnvalidatedModels method to useModelConfig hook
- Add Switch toggle in model-config-dialog footer
- Update model-selector to filter based on showUnvalidatedModels setting
- Add warning icon for unvalidated models in the selector
- Add i18n translations for en/zh/ja
Closes#410🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: wrap AlertTriangle in span for title attribute
The AlertTriangle icon from lucide-react doesn't support the title prop directly.
Wrapped it in a span element to properly display the tooltip.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Button now shows 'Test' by default instead of persisting 'Verified' state
- Verified status is still shown via green badge in provider header
- Updated OpenAI suggested models list with latest GPT-5.x series
Fixes#374 - Models were confused by the `type` field name and sent
`operation` instead. This change:
- Renames DiagramOperation.type to DiagramOperation.operation across
all files (MCP server, web app, hooks, components, system prompts)
- Adds JSON examples in tool descriptions to show correct format
- Updates all test data to use the new field name
Affected files:
- lib/utils.ts
- app/api/chat/route.ts
- hooks/use-diagram-tool-handlers.ts
- components/chat-message-display.tsx
- lib/system-prompts.ts
- packages/mcp-server/src/diagram-operations.ts
- packages/mcp-server/src/index.ts
- scripts/test-diagram-operations.mjs
MCP server version bumped to 0.1.6
* fix: use full IP for userId to prevent quota collision
- Remove .slice(0, 8) from base64 encoded IP
- Each IP now has unique userId (no /16 collision)
- Affects: quota tracking, Langfuse tracing
* refactor: extract getUserIdFromRequest to shared utility
- Create lib/user-id.ts with shared function
- Fix misleading 'privacy' comment (base64 is not privacy)
- Remove duplicate code from chat and log-feedback routes
- Fixed bug where daily quota counts weren't resetting on new day
(if_not_exists only works for missing attributes, not day changes)
- Changed to two-phase approach: reset if new day, then increment
- Added QUOTA_TIMEZONE env var for local midnight reset (e.g., Asia/Tokyo)
- Added timezone validation with UTC fallback
- Add HTML escaping (<, >) in convertToLegalXml for attribute values
- Update isMxCellXmlComplete to handle any LLM provider's wrapper tags
- Add wrapper tag stripping in wrapWithMxFile for DeepSeek/Anthropic tags
- Update autoFixXml to escape both < and > in attribute values
Fixes 'Malformed XML detected in final output' error when AI generates
diagrams with HTML content in value attributes like <b>Title</b>.
- Parse JSON error response from server to get actual used/limit values
- Previously showed 0/0 due to race condition (config fetch vs error)
- AI SDK puts full response body in error.message for non-OK responses
- Updated all quota toasts (request, token, TPM) to use server values
Third-party OpenAI-compatible proxies typically don't support the
/responses endpoint. Use .chat() for custom baseURLs while keeping
Responses API for official OpenAI to preserve reasoning model support.
Fixes#377
- Add extractCompleteMxCells() to extract only complete mxCell elements from partial XML
- Remove useEffect cleanup that was killing debounce timeouts on every re-render
- Wrap XML in <root> tags for proper DOMParser validation
Previously, diagrams only rendered after ALL XML finished streaming because:
1. useEffect cleanup cleared the 150ms debounce timeout on every message change
2. DOMParser rejected partial XML like '<mxCell id="2" value="...' (incomplete)
Now each complete mxCell renders progressively as it finishes streaming.
- Add dynamo-quota-manager.ts for atomic quota checks using ConditionExpression
- Enforce daily request limit, daily token limit, and TPM limit
- Return 429 with quota details (type, used, limit) when exceeded
- Quota is opt-in: only enabled when DYNAMODB_QUOTA_TABLE env var is set
- Remove client-side quota enforcement (server is now source of truth)
- Simplify use-quota-manager.tsx to only display toasts
- Add @aws-sdk/client-dynamodb dependency
- Use Responses API instead of Chat Completions API for OpenAI
(.chat() -> default call) to support reasoning events
- Add o4 to reasoning model detection
- Change default reasoningSummary from 'detailed' to 'auto'
(not all models support 'detailed')
- Update types to match AI SDK: 'auto' | 'detailed'
- Add ~40 new translation keys for model-config-dialog and model-selector
- Support English, Chinese, and Japanese translations
- Replace all hardcoded strings with dictionary lookups
* feat: support subdirectory deployment (NEXT_PUBLIC_BASE_PATH)
* removed unwanted check and fix favicon issue
* Use getAssetUrl for manifest assets to avoid undefined NEXT_PUBLIC_BASE_PATH
* Add validation warning for NEXT_PUBLIC_BASE_PATH format
---------
Co-authored-by: dayuan.jiang <jdy.toh@gmail.com>
* fix:custom model setting bug
* refactor: consolidate aiProvider checks for cleaner code
* fix:Integrated the language selection option into the `SettingsDialog`
* fix:useSearchParams() should be wrapped in a suspense boundary at page
* fix: improve semantic HTML and maintainability
- Replace nested button>a with proper anchor element for GitHub link
- Use i18n.locales.map() with LANGUAGE_LABELS for language options
---------
Co-authored-by: dayuan.jiang <jdy.toh@gmail.com>
* feat: add multi-provider model configuration
- Add model config dialog for managing multiple AI providers
- Support for OpenAI, Anthropic, Google, Azure, Bedrock, OpenRouter, DeepSeek, SiliconFlow, Ollama, and AI Gateway
- Add model selector dropdown in chat panel header
- Add API key validation endpoint
- Add custom model ID input with keyboard navigation
- Fix hover highlight in Command component
- Add suggested models for each provider including latest Claude 4.5 series
- Store configuration locally in browser
* feat: improve model config UI and move selector to chat input
- Move model selector from header to chat input (left of send button)
- Add per-model validation status (queued, running, valid, invalid)
- Filter model selector to only show verified models
- Add editable model IDs in config dialog
- Add custom model input field alongside suggested models dropdown
- Fix hover states on provider buttons and select triggers
- Update OpenAI suggested models with GPT-5 series
- Add alert-dialog component for delete confirmation
* refactor: revert shadcn component changes, apply hover fix at usage site
* feat: add AWS credentials support for Bedrock provider
- Add AWS Access Key ID, Secret Access Key, Region fields for Bedrock
- Show different credential fields based on provider type
- Update validation API to handle Bedrock with AWS credentials
- Add region selector with common AWS regions
* fix: reset Test button after validation completes
* fix: reset validation button to Test after success
* fix: complete bedrock support and UI/UX improvements
- Add bedrock to ALLOWED_CLIENT_PROVIDERS for client credentials
- Pass AWS credentials through full chain (headers → API → provider)
- Replace non-existent GPT-5 models with real ones (o1, o3-mini)
- Add accessibility: aria-labels, focus-visible rings, inline errors
- Add more AWS regions (Ohio, London, Paris, Mumbai, Seoul, São Paulo)
- Fix setTimeout cleanup with useRef on component unmount
- Fix TypeScript type consistency in getSelectedAIConfig fallback
* chore: remove unused code
- Remove unused setAccessCodeRequired state in chat-panel.tsx
- Remove unused getSelectedModel export in model-config.ts
* fix: UI/UX improvements for model configuration dialog
- Add gradient header styling with icon badge
- Change Configuration section icon from Key to Settings2
- Add duplicate model detection with warning banner and inline removal
- Filter out already-added models from suggestions dropdown
- Add type-to-confirm for deleting providers with 3+ models
- Enhance delete confirmation dialog with warning icon
- Improve model selector discoverability (show model name + chevron)
- Add truncation for long model names with title tooltip
- Remove AI provider settings from Settings dialog (now in Model Config)
- Extract ValidationButton into reusable component
* fix: prevent duplicate model IDs within same provider
- Block adding model if ID already exists in provider
- Block editing model ID to match existing model in provider
* fix: improve duplicate model ID notifications
- Add toast notification when trying to add duplicate model
- Allow free typing when editing model ID, validate on blur
- Show warning toast instead of blocking input
* fix: improve duplicate model validation UX in config dialog
- Add inline error display for duplicate model IDs
- Show red border on input when error exists
- Validate on blur with shake animation for edit errors
- Prevent saving empty model names
- Clear errors when user starts typing
- Simplify error styling (small red text, no heavy chips)
* feat(mcp): add XML validation and auto-fix to MCP server
- Add xml-validation.ts with validateAndFixXml function
- Integrate validation into display_diagram tool (fails if unfixable)
- Integrate validation into edit_diagram tool (auto-fix each operation)
- Fix bug: typo fixes now run before foreign tag removal
- Fix bug: use before/after comparison instead of regex .test()
* style: auto-format with Biome
* chore(mcp): bump version to 0.1.3
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* feat: add get_shape_library tool for AI icon discovery
- Add server-side tool that returns shape library documentation
- AI can fetch icon/shape names on-demand before generating diagrams
- Includes path traversal protection and input sanitization
- Library index embedded in tool description for discoverability
- Supports 33 libraries: AWS, Azure, GCP, Kubernetes, Cisco, etc.
* fix: improve get_shape_library error handling and imports
- Move fs/path imports to top of file (avoid dynamic imports per call)
- Distinguish file-not-found vs other errors in catch block
- Include invalid input in validation error message
- Log unexpected errors for debugging
* docs: add get_shape_library to system prompt tool list
- Add Tool4 (get_shape_library) to available tools section
- Add usage guidance in 'Choose the right tool' section
- Update AWS icons note to reference get_shape_library for icon discovery
* fix: display get_shape_library tool output in chat UI
* fix: correct state check for get_shape_library output display
* fix: make get_shape_library output respect fold state
* style: auto-format with Biome
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* feat: add support for custom AI Gateway base URL
- Add createGateway support with configurable baseURL
- Allow AI_GATEWAY_BASE_URL environment variable for:
* Local development with custom Gateway
* Self-hosted AI Gateway deployments
* Enterprise proxy configurations
- Maintain backward compatibility: defaults to Vercel Gateway when not set
- Update documentation with usage examples and configuration notes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: remove errant character in error message
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: dayuan.jiang <jdy.toh@gmail.com>
* feat: add Vercel AI Gateway support
- Updated environment configuration to include AI_GATEWAY_API_KEY for unified access to multiple AI providers.
- Added gateway provider to the list of supported AI providers in the codebase.
- Enhanced documentation to explain the usage of Vercel AI Gateway and its model format.
This change simplifies authentication and allows users to switch between providers seamlessly.
* Update package
@ai-sdk/gateway to latest version 2.0.21
* refactor: replace text-based edit_diagram with ID-based operations
- Add applyDiagramOperations() function using DOMParser for ID lookup
- New schema: operations array with type (update/add/delete), cell_id, new_xml
- Update chat-panel.tsx handler for new operations format
- Update OperationsDisplay component to show operation type and cell_id
- Simplify system prompts with new ID-based examples
- Add ID validation for add operations
- Add warning for edges referencing deleted cells
* fix: add ID validation to update operation and remove dead code
- Add ID mismatch validation to update operation (consistency with add)
- Remove orphaned replaceXMLParts function (~300 lines of dead code)
- Update cell_id schema description for clarity
- Add unit tests for applyDiagramOperations (11 tests)
* feat: add minimal style mode toggle for faster diagram generation
- Add Minimal/Styled toggle switch in chat input UI
- When enabled, removes color/style instructions from system prompt
- Faster generation with plain black/white diagrams
- Improves XML auto-fix: handle foreign tags, extra closing tags, trailing garbage
- Fix isMxCellXmlComplete to strip Anthropic function-calling wrappers
- Add debug logging for truncation detection diagnosis
* fix: prevent false XML parse errors during streaming
- Escape unescaped & characters in convertToLegalXml() before DOMParser validation
- Only log console.error for final output, not during streaming updates
- Prevents Next.js dev mode error overlay from showing for expected streaming states
* refactor: simplify LLM XML format to output bare mxCells only
- Update wrapWithMxFile() to always add root cells (id=0, id=1) automatically
- LLM now generates only mxCell elements starting from id=2 (no wrapper tags)
- Update system prompts and tool descriptions with new format instructions
- Update cached responses to remove root cells and wrapper tags
- Update truncation detection to check for complete mxCell endings
- Update documentation in xml_guide.md
* fix: address PR review issues for XML format refactor
- Fix critical bug: inconsistent truncation check using old </root> pattern
- Fix stale error message referencing </root> tag
- Add isMxCellXmlComplete() helper for consistent truncation detection
- Improve regex patterns to handle any attribute order in root cells
- Update wrapWithMxFile JSDoc to document root cell removal behavior
* fix: handle non-self-closing root cells in wrapWithMxFile regex
* feat: add append_diagram tool for truncation continuation
When LLM output hits maxOutputTokens mid-generation, instead of
failing with an error loop, the system now:
1. Detects truncation (missing </root> in XML)
2. Stores partial XML and tells LLM to use new append_diagram tool
3. LLM continues generating from where it stopped
4. Fragments are accumulated until XML is complete
5. Server limits to 5 steps via stepCountIs(5)
Key changes:
- Add append_diagram tool definition in route.ts
- Add append_diagram handler in chat-panel.tsx
- Track continuation mode separately from error mode
- Continuation mode has unlimited retries (not counted against limit)
- Error mode still limited to MAX_AUTO_RETRY_COUNT (1)
- Update system prompts to document append_diagram tool
* fix: show friendly message and yellow badge for truncated output
- Add yellow 'Truncated' badge in UI instead of red 'Error' when XML is incomplete
- Show friendly error message for toolUse.input is invalid errors
- Built on top of append_diagram continuation feature
* refactor: remove debug logs and simplify truncation state
- Remove all debug console.log statements
- Remove isContinuationModeRef, derive from partialXmlRef.current.length > 0
* docs: fix append_diagram instructions for consistency
- Change 'Do NOT include' to 'Do NOT start with' (clearer intent)
- Add <mxCell id="0"> to prohibited start patterns
- Change 'closing tags </root></mxGraphModel>' to just '</root>' (wrapWithMxFile handles the rest)
* fix: improve Azure provider auto-detection and validation (#223)
- Fix detectProvider() to only detect Azure when it has complete config
(both AZURE_API_KEY and AZURE_RESOURCE_NAME or AZURE_BASE_URL)
- Add validation in validateProviderCredentials() for Azure to provide
clear error messages when configuration is incomplete
- Update docs/ai-providers.md to clarify Azure requires resource name
* docs: add Azure reasoning options to documentation
Add NEXT_PUBLIC_MAX_EXTRACTED_CHARS environment variable to allow
configuring the maximum characters extracted from PDF and text files.
Defaults to 150000 (150k chars) if not set.
Previously AZURE_RESOURCE_NAME was documented in env.example but not
actually used in the code. This caused Azure OpenAI configuration to fail
when users set AZURE_RESOURCE_NAME instead of AZURE_BASE_URL.
Changes:
- Read AZURE_RESOURCE_NAME from environment and pass to createAzure()
- resourceName constructs endpoint: https://{name}.openai.azure.com/openai/v1
- baseURL takes precedence over resourceName when both are set
- Updated env.example with clearer documentation
Fixes#208