Commit graph

23 commits

Author SHA1 Message Date
Kayshen Xu
ca1b5370ae
V0.3.0 (#24)
* feat(boolean-operations): implement boolean operations in the editor

- Added a new BooleanToolbar component for union, subtract, and intersect operations.
- Integrated boolean operations into the layer context menu and keyboard shortcuts.
- Enhanced the editor layout to include the boolean toolbar for improved user interaction.
- Updated internationalization support with new translation keys for boolean operations.
- Bumped version to 0.3.0 to reflect the addition of these features.

* refactor(editor): update editor layout and panels for improved functionality

- Replaced the PropertyPanel with a new RightPanel that includes both Property and Code panels.
- Removed the CodePanel from the main editor layout and integrated it into the RightPanel.
- Updated keyboard shortcuts to switch the right panel to the code tab.
- Enhanced the LayerPanel with a resizable width feature for better user experience.
- Added internationalization support for new right panel labels and code panel features.
- Introduced new code generation capabilities for various frameworks in the CodePanel.
- Improved overall layout structure for better responsiveness and usability.

* feat(electron): implement .op file association and enhance file handling

- Added support for .op file association in electron-builder, allowing OpenPencil documents to be opened directly from the file system.
- Implemented IPC handlers for opening and reading .op files, ensuring proper loading of document content.
- Enhanced the main process to handle file opening events on macOS and single-instance locking on Windows/Linux.
- Updated the renderer to listen for file open events and load documents accordingly.
- Improved README to reflect new file association feature.

* fix(canvas): improve layout accuracy for AI-generated designs

- Unify lineHeight default via canonical defaultLineHeight() function
- Unify text measurement by removing duplicate estimators in generation-utils
- Fix optical centering formula to scale proportionally with fontSize
- Round layout positions to whole pixels to prevent sub-pixel artifacts
- Recursively sanitize nested x/y in streaming layout containers
- Fix input trailing icon alignment using fill_container instead of space_between

* feat(canvas): right-align agent badge and add breathing glow border

- Agent badge now right-aligned to frame's right edge instead of after label
- Added breathing glow border around agent-owned frames during generation
- Glow border uses same color and lifecycle as the agent badge
- Removed unused BADGE_GAP constant and useDocumentStore import

* feat(code-panel): enhance tab scrolling functionality and add scrollbar utility

- Introduced left and right scroll buttons for tab navigation in the CodePanel, improving user experience for navigating long tab lists.
- Added a custom utility to hide scrollbars for a cleaner interface.
- Updated styles for better responsiveness and usability in the CodePanel layout.

* fix(docs): update Discord invite links in multiple README files

- Replaced outdated Discord invite links with the new link across all language-specific README files.
- Ensured consistency in the documentation for community engagement.

* feat(code-panel): enhance system prompt for responsive design

- Updated the ENHANCE_SYSTEM_PROMPT to emphasize the importance of responsive design in code rewriting.
- Added detailed guidelines for converting fixed pixel widths to relative units and using responsive Tailwind breakpoints.
- Ensured that the output remains visually faithful on desktop while adapting gracefully across screen sizes.

* feat(docs): add WeChat group information to README.zh.md and include group image

- Introduced a new section in the Chinese README to provide details about the WeChat group for community engagement.
- Added an image representing the WeChat group for better visibility and user interaction.

* feat(electron): enhance theme management and title bar overlay for Windows/Linux

- Updated the `setTheme` method in the Electron API to accept custom colors for the title bar overlay, improving theme synchronization across platforms.
- Adjusted title bar overlay colors for Windows and Linux to ensure proper visibility and aesthetics.
- Enhanced the top bar component to read computed CSS colors and apply them dynamically, ensuring a consistent user interface.
- Improved handling of theme changes in the application to support background and foreground color customization.

* fix(screenshot): update screenshot image for improved clarity and quality

* fix(docs): update WeChat group image path in README.zh.md for consistency

* fix(ai): fix post-generation validation pipeline and text centering

- Fix Agent SDK validation: save temp screenshots inside project dir
  (.openpencil-tmp/) so Claude Code plan mode can read them, instead
  of /tmp/ which is outside the project sandbox
- Enrich validation tree dump with fill colors, stroke, fontSize,
  fontWeight, textAlign, cornerRadius, opacity for comprehensive
  visual analysis
- Add multi-round validation with quality scoring (threshold 8/10),
  500ms stabilization delay between rounds
- Add detailed debug logging to applyValidationFixes showing which
  nodes were found/skipped and property changes
- Fix canvas sync needsTextbox check to also account for textAlign
  (matching isFixedWidthText in factory), preventing IText↔Textbox
  thrashing on every sync tick
- Auto-center text in vertical+center layouts by expanding to full
  container width and injecting textAlign:'center'
- Force Textbox for non-left-aligned text so textAlign is respected
  (IText ignores width and computes its own)

* fix(canvas): use precise text width estimation for fit-content layout

Remove the 14% safety factor from text width estimation when computing
fit-content/natural-width text dimensions. IText auto-computes its own
width and ignores our setting, so the safety margin only inflated the
layout allocation, making text appear left-shifted within its container.

* fix(canvas): center fit-content text in horizontal layouts

For text nodes with fit-content width in horizontal layouts, set
textAlign:'center' to compensate for width estimation inaccuracy.
The estimated box is typically wider than the actual rendered text,
causing left-aligned text to appear visually shifted. Centering
distributes the estimation error evenly on both sides.

* feat(ai): show validation details in checklist panel

- Accumulate validation log (screenshot, analysis, fixes) instead of
  overwriting status messages, so the full process is visible
- Preserve step thinking content in buildFinalStepTags (was discarded)
- Add details field to pipeline items and render in checklist UI
- Each validation step now shows: screenshot captured, issues found,
  quality score, fixes applied

* feat(ai): add visual reference pipeline types and integration hooks

- Add DesignSystem and VisualReference types to ai-types
- Add 'visual-ref' mode to AIDesignRequest and SubTask.htmlReference
- Detect visual-ref candidates in chat handlers (landing pages, websites)
- Wire visual-ref mode in design-generator and orchestrator
- Inject HTML reference snippets into sub-agent prompts

* feat(ai): add modular design principles for sub-agent context

- Add design-principles module with topic files: color, typography,
  spacing, composition, components
- Selectively load relevant principles based on prompt content
- Inject design principles into sub-agent system prompts

* feat(ai): implement visual reference pipeline

- Add design-system-generator: generates color/typography/spacing tokens
- Add design-code-generator: generates HTML/CSS from design system
- Add html-renderer: renders HTML to screenshot via html2canvas
- Add visual-ref-orchestrator: coordinates the full pipeline
  (design system → HTML code → screenshot → enrich subtasks)
- Add html2canvas dependency for client-side HTML rendering

* feat(mcp): default filePath to live canvas and fix cross-platform issues

- Default all MCP tool filePath to live://canvas when omitted, so tools
  operate on the real-time canvas instead of stale files
- Remove filePath from required params in all tool schemas (21 interfaces)
- Fix mcp-server-manager.ts using process.cwd() which fails in Electron
  production on Linux — now checks ELECTRON_RESOURCES_PATH first
- Fix stopMcpHttpServer using SIGTERM on Windows — use taskkill instead
- Force new children reference in applyExternalDocument to ensure canvas
  sync subscriber always detects MCP-pushed document updates

* feat(mcp): enhance design prompt with semantic roles, CJK typography, and layout rules

Add comprehensive design knowledge to MCP design prompt for better
AI-generated designs: design type detection (mobile vs desktop), full
semantic role reference with context-aware defaults, CJK typography
rules, expanded text/layout/form guidelines, and detailed post-processing
documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(ai): implement intent classification for chat handlers

- Replace hardcoded keyword matching with a lightweight LLM call to classify user intent in chat messages.
- Introduce a new function `classifyIntent` to determine if the request is for design generation or conversation.
- Update design request handling in `useChatHandlers` to utilize the new classification method.
- Enhance design prompt documentation to reflect changes in design type detection based on intent rather than keywords.

* fix(ai): handle string qualityScore in validation response parsing

The LLM sometimes returns qualityScore as a string (e.g. "8" instead of 8),
causing it to fall through to 0. Also hide misleading "quality: 0/10" display
when the score couldn't be determined, and log raw response for debugging.

* fix(ai): increase validation timeout to 90s and fix quality score parsing

Agent SDK validation requires spawning a process, reading the image, and
analyzing it — 30s was consistently timing out. Also handle string
qualityScore values from LLM responses and hide misleading 0/10 display.

* fix(ai): fix validation timeout and response parsing

- Increase validation timeout from 30s to 180s (Agent SDK needs time
  for subprocess spawn + OAuth auth + multi-turn image reading)
- Strip <tool_use> XML blocks from Agent SDK response before extracting
  JSON — the tool call XML was confusing the regex, causing qualityScore
  to parse as 0 despite valid JSON being present
- Handle string qualityScore values and hide misleading "quality: 0/10"
- Revert unnecessary direct API key approach for validation

* fix(ai): prevent node ID collisions between generations

When generating new content on a canvas with existing nodes, AI-generated
IDs (e.g. brand-spacer) would collide with previous generations. Now
captures pre-existing node IDs at generation start and checks against
them during upsert sanitization. Remapped IDs are tracked in
generationRemappedIds so progressive streaming updates can still find
their nodes.

* fix(ai): require styleGuide in orchestrator plan and fix validation detail icons

- Add fallback default styleGuide when orchestrator LLM omits it
- Strengthen prompt to mark styleGuide as REQUIRED
- Replace emoji icons in validation details with [done]/[pending]/[error]
  markers for consistent styling with the checklist design system

* feat(server): add port file plugin for server instance discovery

- Introduce a new Nitro plugin that writes a port file on server startup to allow the MCP server to discover the running instance, whether it's a development server or Electron.
- Implement error handling in the Electron main process for writing the port file, logging any failures.
- Update Vite configuration to include additional external dependencies in the rollup configuration.

* feat(electron): implement IPC for retrieving pending file paths

- Added a new IPC handler `file:getPending` to retrieve and clear the pending file path when the React app mounts.
- Updated the Electron API to include `getPendingFile` for renderer access.
- Enhanced the `useElectronMenu` hook to load any pending file on application startup.
- Updated UI components to reflect changes in file handling and improved user experience.

* fix(panels): replace emoji icons with styled icons in validation checklist

- Parse [done]/[pending]/[error] prefixes in detail lines and render as
  styled circle icons matching the parent checklist design system
- Replace remaining emoji markers in design-validation.ts with text prefixes
- Fix isApplied detection to recognize new [done] Applied marker

* refactor(electron): update settings path to use platform-standard app data directory

- Changed the settings file path to utilize Electron's user data directory for better cross-platform compatibility.
- Updated the settings writing function to ensure the user data directory is created if it doesn't exist.
- Added comments to clarify the storage location for different operating systems.
- Implemented a fixed partition for localStorage/cookies to maintain data across server port changes.

* feat(ai): enhance validation with pre-checks, structural fixes, and border detection

- Add design-pre-validation.ts: pure code checks before LLM validation
  - Invisible container detection (same fill as parent → auto-add border)
  - Sibling consistency (majority-rule for height/cornerRadius)
- Add structural fixes to validation: addChild/removeNode operations
  - Icon injection via lookupIconByName with server fallback
  - autoFixParentLayout with child count guard to prevent layout breakage
- Add strokeColor/strokeWidth to safe fix properties for border fixes
- Simplify intent classification: all design requests use visual-ref pipeline
- Fix checklist: "Found N issues" now shows [done] instead of [pending]
- Fix qualityScore: only update when > 0 to preserve valid round scores

* fix(ai): cherry-pick safe validation improvements, drop aggressive pre-checks

Keep: stroke tree dump bug fix (object not array), qualityScore=0 false
positive detection, fit_content→fixed safety guard, empty path removal,
type-specific sibling consistency, repeated fix filtering, screenshot
extraction to design-screenshot.ts.

Drop: detectForcedFixedHeight (destroyed input/button heights),
MAX_VALIDATION_ROUNDS 5 (too many rounds), removal of quality threshold
early stop, section regeneration phase.

---------

Co-authored-by: Fini <fini.yang@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:55:35 +08:00
Kayshen Xu
5e13f48be1
V0.2.1 (#23)
* feat(ai): integrate GitHub Copilot support and enhance agent management

- Added GitHub Copilot as a new AI provider, including connection and installation handling.
- Updated agent settings to include Copilot in the configuration options.
- Enhanced the chat API to support Copilot as a provider, allowing for model selection and streaming responses.
- Implemented installation instructions for Copilot CLI within the application.
- Updated UI components to display Copilot status and connection options.
- Enhanced internationalization support with new translations for Copilot-related terms.

Bump version to 0.2.1.

* feat(electron): enhance theme management for Windows/Linux

- Added support for dynamic title bar overlay based on theme selection for Windows and Linux platforms.
- Implemented auto-hide menu bar functionality for improved user experience on Windows/Linux.
- Updated Electron API to include a new `setTheme` method for theme synchronization.
- Modified top bar component to trigger theme changes via the new API, ensuring consistent UI across platforms.

* feat(electron): add Linux window controls detection and styling

- Implemented a function to detect the position of window controls on Linux, supporting both left and right placements based on desktop environment settings.
- Updated the main window styling to adjust control padding dynamically for Linux and Windows platforms, ensuring a consistent user interface across operating systems.
- Modified the top bar component to include specific class names for better control layout management.

* fix(electron): update title bar overlay color and height for consistency

- Changed title bar overlay color to transparent (rgba(0,0,0,0)) for improved aesthetics.
- Adjusted height of the title bar from 40 to 36 pixels to enhance visual alignment across platforms.

* fix(editor): adjust position of update ready banner for improved visibility

- Moved the update ready banner from top-5 to top-12 to enhance its visibility and prevent overlap with other UI elements.
2026-03-06 21:00:42 +08:00
Kayshen Xu
3fb029d9a7
V0.2.0 (#21)
* feat(ai): add agent identity system with visual indicators for concurrent generation

- Agent identity: assign unique colors and names to each sub-agent
- Canvas indicators: breathing glow border + name pill above streaming nodes
- Preview effect: outline appears 500ms before element materializes
- Screen grouping: subtasks with same `screen` field share one root frame,
  fixing multi-page apps being split into too many frames
- Screen-level parallelism: subtasks within same screen run sequentially
  (preserving section order), different screens run in parallel

* fix(canvas): make agent indicator visual effect much more dramatic

- Outer glow: 8px soft border for visible halo effect
- Inner border: 2.5px sharp crisp border at high alpha
- Preview fill: 10-15% alpha (was ~1% before, essentially invisible)
- Breathing: faster cycle (400ms), higher range [0.35, 0.95]
- Name pill: larger font (11px), bold 700, drop shadow
- Pill dedup: only draw one name pill per agent (not per node)
- Rounded rect helper for polished pill rendering

* fix(canvas): use globalThis for agent indicator state to prevent module isolation

Vite module splitting can create separate module instances for the same
file when imported from different chunks. This causes the indicator Map
written by the orchestrator (services/ai/) to be a different instance
than the one read by the canvas hook (canvas/). Using globalThis
guarantees a single shared instance across all chunks.

* feat(i18n): enhance internationalization support by integrating i18next for translation in various components. Added new dependencies: i18next, i18next-browser-languagedetector, and react-i18next. Updated UI elements in the editor, toolbar, and status bar to utilize translation keys for improved localization. Enhanced README with language options for better accessibility.

* feat(auto-update): implement auto-update functionality with settings management

- Added auto-update feature to check for updates at app startup and periodically while running.
- Introduced settings for enabling/disabling auto-update, stored in a JSON file.
- Integrated IPC handlers to manage auto-update settings from the renderer process.
- Created new API endpoints for managing MCP server status, including start/stop functionality.
- Enhanced the UI to support theme presets, allowing users to save and load variable presets.
- Updated internationalization support for new UI elements related to auto-update and presets.

* feat(ai): add element boundaries to orchestrator subtask planning

Orchestrator now outputs an "elements" field per subtask listing the
specific UI elements it owns. Sub-agent prompts display these boundaries
so each agent knows exactly what to generate and what belongs to other
sections, preventing content duplication across subtasks.

Also includes: sequential cascade reveal animation, agent indicator
recursive tagging, delayed indicator removal, single-agent identity
for sequential mode, model name truncation fix.

---------

Co-authored-by: Fini <fini.yang@gmail.com>
2026-03-05 21:14:50 +08:00
Kayshen Xu
ced993c388
V0.1.2 (#19)
* Security hardening: fix critical and high-severity vulnerabilities (#18)

* feat(mcp): add sanitizeObject utility to strip prototype pollution keys

Recursively removes __proto__, constructor, and prototype keys from
parsed JSON objects to prevent prototype pollution attacks via
malicious .op files or batch_design DSL input.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(electron): validate file path in saveToPath IPC handler

Prevent path traversal attacks by checking for null bytes and restricting
file extensions to .op and .pen only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(mcp): guard against prototype pollution in document parsing and batch design

Sanitize JSON.parse output in openDocument() and parseJsonArg() to strip
__proto__, constructor, and prototype keys before processing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ai): sanitize debug logs and harden temp file handling

Filter credential patterns from debug tail before sending to client.
Set restrictive 0o700 permissions on temp directory. Validate attachment
media types against allowlist to prevent extension spoofing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ai): restrict environment variables passed to codex subprocess

Replace full process.env with explicit allowlist of PATH, HOME, TERM,
LANG, SHELL, TMPDIR, and OPENAI_*/CODEX_* prefixed vars only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(figma): add decompression size limits to prevent zip bombs

Enforce 100MB total unzipped size and 50MB per-image limits during
.fig file extraction to guard against malicious archives.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(canvas): add dangerous SVG tags to skip list and fix ReDoS in getAttr

Strip script, foreignObject, animate, animateMotion, and set elements
during SVG import. Escape regex-special characters in style attribute
name lookup to prevent ReDoS.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(security): add unit tests for security hardening fixes

27 tests covering: sanitizeObject prototype pollution stripping,
document-manager sanitization, batch-design DSL sanitization,
codex env allowlist, debug tail credential filtering, media type
validation, SVG skip tags, and ReDoS safety.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat(mcp): add live canvas sync and HTTP transport support

Introduce real-time MCP ↔ renderer sync via SSE (server/api/mcp endpoints,
use-mcp-sync hook, mcp-sync-state). Add StreamableHTTPServerTransport for
HTTP and dual stdio+http modes. Electron writes ~/.openpencil/.port for MCP
discovery. New design_prompt tool. Agent settings dialog gains transport
mode selector. Security: restrict Electron file writes to home/temp dirs.
Bump version to 0.1.2.

---------

Co-authored-by: RolandSherwin <RolandSherwin@protonmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:08:52 +08:00
Kayshen Xu
3eca24ac5a
V0.1.1 (#17)
* chore(electron): update mac build scripts for improved artifact handling

- Modified the `electron:build:mac-arm64` script to rename the generated YAML file for better clarity.
- Adjusted the `electron:build:mac-both` script to run builds sequentially without file renaming logic, ensuring consistent output.

* chore(electron): enable notarization for macOS builds and update build workflow secrets

- Added notarization support in `electron-builder.yml` for enhanced security.
- Updated GitHub Actions workflow to include necessary Apple credentials for notarization.

* chore(electron): add additional secrets for macOS notarization in build workflow

- Included CSC_LINK and CSC_KEY_PASSWORD in the GitHub Actions workflow to support code signing for macOS builds.

* feat(types): add ImageFitMode type and objectFit to ImageNode

Support fill/fit/crop/tile image scaling modes, matching Figma's
image fill behavior. Default is 'fill' (cover) for backward compat.

* feat(canvas): render images per fill mode with native crop

Add computeImageTransform helper supporting fill/fit/crop/tile modes.
Fill/crop uses FabricImage native cropX/cropY instead of clipPath to
avoid conflict with parent frame clipping. Tile mode creates a Rect
with Pattern fill. Detect mode changes via __needsRecreation flag for
object recreation when switching between tile and non-tile modes.

* feat(panels): add image fit mode dropdown to property panel

New ImageSection component with Fill/Fit/Crop/Tile dropdown for
image nodes. Wired into PropertyPanel between icon and appearance
sections.

* feat(figma): preserve image scale mode from Figma import

Map Figma imageScaleMode (FIT/FILL/TILE) to objectFit property on
imported ImageNodes so fill mode is preserved across import.

* fix(canvas): fix zoom-to-fit bounds inflated by clipped children

computeDocBounds was recursing into frame children, inflating the
bounding box beyond visible frame bounds. Now only recurses into
groups. Also use double-RAF in Figma import for reliable timing.

* feat(figma): implement Figma clipboard paste functionality

- Added a new hook, useFigmaPaste, to handle pasting Figma clipboard data into the canvas.
- Integrated clipboard data extraction and processing to convert Figma nodes into PenNodes.
- Enhanced keyboard shortcuts to attempt reading Figma data from the system clipboard as a fallback.
- Introduced utility functions for decoding and processing Figma clipboard HTML data.
- Updated editor layout to utilize the new Figma paste functionality.

* feat(figma): implement Figma clipboard support for pasting nodes

- Added a new hook, `useFigmaPaste`, to handle Figma clipboard data extraction and processing.
- Integrated Figma clipboard support into the editor layout and keyboard shortcuts for seamless pasting.
- Updated README to reflect changes in file format from `.pen` to `.op`.
- Refactored AI service methods to route to appropriate provider SDK based on the `provider` field, enhancing flexibility in AI interactions.

* fix(figma): preserve imported node order and disable openpencil auto layout

Prevent imported/generated nodes from being prepended in auto-layout containers, which could reverse visual order during progressive insertion.

Hide the unfinished OpenPencil auto-layout path from the import dialog to avoid selecting a mode that is not ready yet.

* fix(ai): enforce explicit provider and model routing

Pass selected provider and model through design generation, orchestration, sub-agent, and validation flows.

Disable provider/model fallback and remove model retry-without-selection behavior so requests fail fast instead of silently routing to Claude.

* chore(package): bump version to 0.1.1

---------

Co-authored-by: Fini <fini.yang@gmail.com>
2026-03-02 22:26:09 +08:00
Kayshen Xu
80636b0d5b
V0.1.0 (#13)
* feat(editor): implement Figma import functionality

- Added a new FigmaImportDialog component for importing .fig files.
- Integrated file processing and conversion logic to handle Figma files.
- Enhanced the editor layout to include a button for opening the Figma import dialog.
- Introduced page tabs for better navigation between document pages.
- Updated various components to utilize active page children for rendering and interactions.
- Added new dependencies: fzstd and kiwi-schema for improved functionality.

* fix(ai): harden Claude agent env variable resolution

- Filter empty strings and object values from settings.json env
- Validate ANTHROPIC_CUSTOM_HEADERS is valid JSON before passing
- Remove incorrect ANTHROPIC_CUSTOM_HEADERS auto-generation from auth token

* refactor(ai): remove silent fallback logic, surface errors in AI panel

- Remove direct-stream fallback in generateDesign, delegate to orchestrator
- Remove orchestrator planner fallback plan (buildFallbackPlanFromPrompt)
- Remove sub-agent retry logic, minimal mode retry, and placeholder insertion
- Throw on sub-agent error instead of silently degrading
- Call updateLastMessage in catch block so errors display immediately
- Clean up unused imports, functions, and console.log/warn statements

* fix(ai): add 30s API connect timeout for faster error detection

- Set maxRetries: 0 on Anthropic SDK to prevent retry delays on 429
- Add AbortController-based 30s timeout for initial API connection
- If the provider doesn't respond within 30s, abort and send SSE error
- Refactor streamViaAnthropicSDK with shared send() helper

* fix(editor): improve Figma import visual fidelity

- Extract image files from .fig ZIP archive and resolve by SHA-1 hash
- Map Figma textCase property (UPPER/LOWER/TITLE) to text content
- Convert ellipse nodes with image fills to image nodes
- Decode Figma vector paths and match icons via Lucide icon registry
- Fix z-order: move background rectangles behind content layers
- Set clipContent=true for Figma frames (default clip behavior)
- Unwrap single-artboard pages to use artboard as root frame

* fix(canvas): preserve clipPath during async image load and invalidate cache

- Copy clipPath from placeholder rect to FabricImage in onload callback
- Set obj.dirty=true after applying/removing clipPath so Fabric.js
  re-renders with the updated clip region instead of using stale cache

* fix(ai): use page-aware empty frame detection and place new designs as siblings

- Fix isCanvasOnlyEmptyFrame() to use getActivePageChildren() instead of
  document.children which is empty after page migration
- When canvas is empty, replace default frame (existing behavior restored)
- When canvas has content, add generated frame as top-level sibling
  positioned to the right with 100px gap
- Track generationRootFrameId so height adjustment targets correct frame
- Add WIDTH SELECTION rule: app screens use 375x812 mobile dimensions
- Include selected node dimensions in AI context string

* feat(electron): implement application menu with native actions

- Added a native application menu for macOS and Windows, including File, Edit, View, and Window menus.
- Integrated menu actions for creating, opening, saving files, and editing operations like undo/redo.
- Enhanced the editor layout to handle Electron menu actions through a custom hook.
- Updated icon components in the toolbar and top bar for consistent styling.
- Refactored padding and layout components for improved structure and readability.

* fix(canvas): use page-aware children for selection depth resolution

getSelectableNodeIds() used doc.children which is empty under the
pages architecture. Switch to getActivePageChildren() so canvas
selection correctly syncs to the layers panel.

* fix(panels): adjust property panel sections for image nodes

Hide fill/stroke sections (not applicable to images) and show
corner radius section for image elements.

* feat(canvas): implement image corner radius via clipPath

FabricImage does not support rx/ry natively. Use a rounded-rect
clipPath instead, with objectCaching disabled to ensure immediate
re-render on radius changes.

* fix(canvas): use page-aware forcePageResync for canvas re-sync

The old pattern { ...doc, children: [...doc.children] } only touched
root-level children which are empty under pages architecture. Extract
forcePageResync() into canvas-sync-utils and replace all 7 occurrences
across canvas-object-modified, drag-into-layout, and layout-reorder.

* fix(canvas): preserve image corner radius clipPath during drag

Three issues caused corner radius loss on image drag:

1. Scale baking in object:modified changed FabricImage width from
   natural to display dimensions, creating a clipPath size mismatch.
   Exclude images from scale baking (like paths/polygons).

2. object:moving unconditionally cleared all clipPaths to avoid stale
   frame clipping. Now only clears absolutePositioned (frame) clips,
   preserving object-level clips like image corner radius.

3. Post-drag re-sync overwrote the corner radius clipPath with the
   parent frame clip. Now skips frame clip when the object already
   has its own non-absolutePositioned clipPath.

* feat(ai): enhance chat functionality with image attachments support

- Added support for image attachments in chat messages, allowing users to send images alongside text.
- Implemented temporary file handling for attachments, ensuring they are accessible to the AI processing.
- Updated chat message structure to include attachments, and modified the prompt building logic to reference these images.
- Enhanced the chat panel UI to allow users to select and preview images before sending.
- Introduced a new state management for pending attachments in the AI store.
- Refactored related components to accommodate the new attachment feature, improving user experience and interaction.

* feat(multi-page): introduce multi-page architecture and enhance agent settings UI

- Added multi-page architecture to the document structure, allowing for page CRUD actions such as add, remove, rename, reorder, and duplicate.
- Implemented `activePageId` state management in the canvas store for better page handling.
- Enhanced the top bar with an `AgentStatusButton` to display connected AI providers and their statuses.
- Updated the agent settings dialog to improve the UI for managing AI integrations, including better layout and connection indicators.
- Refactored related components for improved usability and visual consistency.

* docs(README): add contributors section with dynamic contributor image

* feat(ai): improve chat streaming and error handling

- Added functionality to hide the checklist when streaming stops with no completed items.
- Implemented abort controller management to handle user-initiated stops during chat generation.
- Enhanced error handling to prevent displaying errors for user-initiated stops while preserving partial content.
- Updated orchestration and design generation functions to support abort signals, improving responsiveness during streaming.

* fix(canvas): align z-order with layer panel convention (top = front)

Establish consistent z-order: children[0] = top of layer panel = frontmost
on canvas. This matches the standard design tool convention (Figma, Sketch).

- Reverse flattenNodes iteration so children[0] is added last to canvas
- Add z-order reconciliation via moveObjectTo after each sync pass
- Figma import: sort children descending so front items are at children[0]
- addNode defaults to prepend (index 0) so new items appear at top
- duplicateNode inserts clone above original (at idx instead of idx+1)
- drag-reparent inserts at index 0 (frontmost) instead of childCount
- Async image loading preserves z-order via insertAt instead of add
- Add FigmaImportLayoutMode toggle (preserve vs openpencil auto-layout)

* chore: resolve .gitignore merge conflict

* fix(canvas): clamp corner radius to half the element height

* chore: update version to 0.1.0 and modify mac artifact naming in electron-builder configuration

---------

Co-authored-by: Fini <fini.yang@gmail.com>
2026-03-01 09:33:52 +08:00
Kayshen Xu
8dde4c43e0
V0.0.2 (#9)
* chore(docs): add video demo to README.md for enhanced project visibility

* refactor(ai): centralize Claude Agent SDK env resolution with debug logging and model retry

Extract shared buildClaudeAgentEnv() and getClaudeAgentDebugFilePath() into
resolve-claude-agent-env.ts to eliminate duplicated env setup across all
server endpoints. Add model fallback retry logic (retry without explicit
model on exit code 1) and diagnostic hints from debug log tail on failures.

* fix(canvas): normalize layout justify/align values from CSS aliases

AI-generated nodes may use CSS-style values like "flex-start",
"space-between", "middle" etc. Add normalizeJustifyContent and
normalizeAlignItems to map these to internal enum values in both
the layout engine and the property panel.

* fix(canvas): improve text and path rendering accuracy

- Remove icon-specific bounding box override on path scaling to prevent
  pathOffset drift that visually offsets icons in logo containers
- Only use Textbox for explicit fixed-width text modes instead of any
  node with width > 0, preventing unwanted word wrapping on auto-width text
- Add widthSafetyFactor for Latin text estimation (1.14x vs 1.06x CJK)
  to reduce accidental line wraps from font width variation

* feat(ai): add input icon affordance rules and trailing icon alignment

Prompt AI to include semantic icons in form inputs (search, password,
email). Add normalizeInputTrailingIconAlignment post-pass in
role-resolver to auto-set justifyContent="space_between" on input
frames with a trailing icon node.

* feat(ai): persist model selection across sessions via localStorage

Add preferredModel and selectModel to ai-store with localStorage
read/write. Hydrate on mount to restore user's last chosen model.
Add isHydrated flag to agent-settings-store to prevent race
conditions during provider list construction.

---------

Co-authored-by: Fini <fini.yang@gmail.com>
2026-02-26 09:38:48 +08:00
Fini
2dbe8aa236 feat(ai): bundle lucide and simple-icons server-side for offline icon resolution
Install @iconify-json/lucide and @iconify-json/simple-icons as server-only
dependencies. Rewrite /api/ai/icon to read from local bundled JSON instead
of fetching from api.iconify.design, eliminating the external network
dependency that caused brand icons to silently fail.

Search order: simple-icons first (brand logos only — no UI name collisions),
then lucide (UI icons). Covers 3670 brand icons and 1729 Lucide icons
with sub-millisecond lookup. No impact on client bundle size.
2026-02-24 04:06:35 +08:00
Fini
19a38a7623 feat(panels): add icon section with library picker and in-place path replacement
- Add IconSection panel shown when a path node with iconId is selected
- Add IconPickerDialog: anchored popover with collection browsing, search,
  current icon highlight, and outside-click/Escape to close
- Add iconId field to PathNode to track Iconify icon identity
- Fix canvas path sync to update d in-place (no object recreation/focus loss)
- Fix multi-element SVG icons: convert circles, rects, lines to path commands
  so shapes like emoji face circles are not dropped during icon replacement
- Filter invisible bounding-box paths (Tabler's M0 0h24v24H0z) before merging
- Preserve original node width/height on icon replace; carry over display color
- Populate iconId in AI icon resolver and server-side Iconify proxy
2026-02-24 00:25:49 +08:00
Kayshen-X
f6747cea32 feat(canvas): enhance canvas functionality with new layout engine, node creation, and object modification features
- Introduced a layout engine for auto-layout computation, including padding resolution and fit-content size calculations.
- Added a node creator for various drawing tools (rectangle, frame, ellipse, line, text) to streamline object creation.
- Implemented object modification handling to sync changes back to the document store, improving interaction with Fabric.js.
- Enhanced text measurement utilities for better width and height estimation, including support for CJK characters.
- Added new API endpoints for AI icon retrieval and validation, supporting multimodal content analysis.
2026-02-23 13:22:17 +08:00
Kayshen-X
b4287245cf feat(build): update electron build configuration and resource handling
- Add mcp-server.cjs to extraResources in electron-builder.yml for production packaging
- Modify package.json build script to include MCP server compilation
- Enhance main.ts to set ELECTRON_RESOURCES_PATH for resource access
- Update mcp-install.ts to resolve MCP server path from resources in production
2026-02-22 12:05:34 +08:00
Kayshen-X
e0d8e4dea8 feat(mcp): implement OpenPencil file format and MCP server integration
- Introduce support for .op file format alongside .pen
- Add MCP server functionality for document management and tool operations
- Implement batch processing tools for design and variable management
- Enhance save and open dialogs to accommodate new file format
- Update dependencies and scripts for MCP server compilation and execution
2026-02-22 11:48:52 +08:00
Fini
5bc192e451 feat(ai): add thinking mode and Codex provider support to server API
- Support thinkingMode/effort params in chat and generate endpoints
- Add Codex (OpenAI) provider streaming via codex-client utility
- Forward thinking config to both Anthropic SDK and Agent SDK paths
2026-02-22 08:19:08 +08:00
Kayshen-X
92dde8ca88 refactor(ai): streamline orchestration and remove complexity classifier
- Remove the complexity classifier as its functionality is no longer needed.
- Update design generator to always route through the orchestrator, simplifying the logic.
- Enhance error handling during orchestration to ensure fallback to direct generation is clear.
- Introduce a new sub-agent prompt for improved output formatting and clarity in design generation.
2026-02-21 17:31:23 +08:00
Kayshen-X
d51510d7e9 feat(electron): integrate Electron framework for desktop application support
- Add Electron configuration and main process setup for building a desktop application.
- Implement IPC communication for file operations (open, save) between the renderer and main processes.
- Create a preload script to expose Electron APIs to the renderer.
- Update package.json to include Electron and related dependencies.
- Enhance the build process with electron-builder for packaging the application.
- Introduce a new electron-builder.yml configuration file for build settings.
- Modify Vite configuration to support Electron-specific builds.
- Update UI components to accommodate Electron's window management and drag regions.
2026-02-20 20:19:06 +08:00
Kayshen-X
0569932381 feat(opencode): integrate OpenCode SDK for enhanced AI interactions
- Add support for OpenCode as a new AI provider, allowing users to connect to a local OpenCode server.
- Implement new API endpoints for generating and streaming chat responses via OpenCode.
- Update UI components to include OpenCode in provider selection and display.
- Introduce OpenCode logo and enhance the agent settings dialog to manage OpenCode connections.
- Refactor existing chat and generation logic to accommodate provider-specific routing.
- Include type definitions for OpenCode SDK to ensure type safety and improve developer experience.
2026-02-20 18:51:05 +08:00
Fini
d939b1c88f fix(canvas,ai): path icon rendering, text centering, and stream reliability
- Path icons: use uniform scaling (preserve aspect ratio instead of squishing),
  fillRule 'evenodd' for compound paths with cutouts, transparent fill for
  stroke-only icons, strokeUniform to keep stroke width constant
- Text centering: use actual Fabric rendered height (fontSize * lineHeight)
  for cross-axis centering instead of declared height
- Hover cursor: use default arrow instead of move/crosshair on elements
- Stream reliability: server sends keep-alive pings every 15s during API TTFT,
  forwards thinking_delta events, client resets timeout on ping/thinking chunks
- Remove silent fallback from streamChat to generateCompletion (was causing
  double requests when server is unresponsive)
- Add 3-minute timeout to generateCompletion
- AI prompts: instruct model to preserve icon aspect ratios
2026-02-20 03:04:13 +08:00
Fini
1664631729 feat(ai): robust design generation with node sanitization and empty frame replacement
- Remove thinking_delta SSE events from server streaming
- Add generateCompletion non-streaming fallback with timeout recovery
- Refactor JSON extraction with multi-block scoring to select best output
- Add node sanitization pipeline: unique ID enforcement, layout child
  position cleanup, screen frame bounds clamping
- Progressive upsert with deep merge preserving earlier phase children
- Replace empty default frame with generated frame (preserving position)
- Enhance AI prompts for improved design output quality
2026-02-19 23:30:12 +08:00
Kayshen-X
a4e0934aa8 feat(chat): enhance chat streaming with 'thinking' state and improve SVG handling in toolbar
- Add support for 'thinking' state in chat message streaming to indicate processing.
- Update toolbar to parse SVG files into editable nodes, allowing for better integration of SVG graphics.
- Refactor image handling to accommodate both SVG and raster images, ensuring proper placement and scaling on the canvas.
- Improve error handling and user feedback during file uploads.
2026-02-19 12:52:30 +08:00
Kayshen-X
1950f8f618 feat(dependencies): update @anthropic-ai/claude-agent-sdk to 0.2.47 and add @anthropic-ai/sdk 0.77.0; enhance error handling in connect-agent and improve chat-message display logic 2026-02-19 11:12:23 +08:00
Fini
30010ad5a3 feat(ai): add Setup Agents & MCP dialog with multi-provider support
- Add agent settings dialog to connect local Claude Code and Codex CLI
- Connect button fetches real models from Agent SDK / Codex models cache
- Provider logos (Claude, OpenAI) as React icon components in top-bar and dialog
- Model selector in AI chat panel grouped by provider with logos and Best badge
- MCP CLI integration toggles (Claude Code, Codex, Gemini, OpenCode, Kiro)
- Persist agent settings to localStorage with hydrate on mount
- Redesign AI chat panel: header, empty state pills, input area, color layering
- Add shadcn Switch component, agent-settings types and Zustand store
2026-02-19 03:15:36 +08:00
Kayshen-X
6cde80454e feat(ai): add model selection and fetching capabilities
Enhance AI chat and generation functionalities by introducing model selection. Update the chat and generation endpoints to accept an optional model parameter. Implement a new API endpoint to fetch available AI models from the server, and integrate model selection into the AI chat panel for improved user experience.
2026-02-18 22:35:17 +08:00
Kayshen-X
6a7a0d0019 feat(ai): integrate AI chat and design generation
Add floating AI assistant panel with streaming chat, design keyword
detection, and automatic PenNode JSON extraction to canvas. Server
endpoints use Anthropic SDK (with API key) or Claude Agent SDK (local
OAuth) as fallback. Panel supports minimize, drag-to-snap, and
quick action presets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:49:41 +08:00