Commit graph

2348 commits

Author SHA1 Message Date
Danila Poyarkov 9f7ce64bf6
Merge pull request #562 from open-pencil/guide-authoring
feat(editor): author canvas and frame guides from rulers
2026-08-20 09:39:19 +03:00
Danila Poyarkov 5acc2235c6 fix(canvas): polish guide ruler interactions 2026-08-20 08:56:33 +03:00
Danila Poyarkov b8d052f5c4 refactor(vue): normalize canvas interaction domains 2026-08-20 08:53:13 +03:00
Danila Poyarkov 3497aef818 refactor(canvas): normalize guide domain naming 2026-08-20 08:47:33 +03:00
Danila Poyarkov 27ad48b365 refactor(canvas): separate guide and overlay pipelines 2026-08-20 08:41:16 +03:00
Danila Poyarkov 197364923b fix(canvas): render live guide drag feedback 2026-08-20 08:23:04 +03:00
Danila Poyarkov d051b26fe9 chore: add Portless development URLs 2026-08-20 08:15:54 +03:00
Danila Poyarkov 581d774d0e fix(canvas): show directional cursors for guides 2026-08-20 07:53:33 +03:00
Danila Poyarkov 23b7d92ecf feat(canvas): support guide selection and editing 2026-08-20 07:50:31 +03:00
Danila Poyarkov 103e4ac151 test(canvas): fix nested guide renderer coverage 2026-08-19 20:28:10 +03:00
Danila Poyarkov c141663291 fix(editor): address guide authoring review
- Dispose CanvasKit dash effects and render nested frame guides
- Validate imported guide GUIDs and invalidate stale raw guide metadata
- Resolve frame owners through nested hit ancestry and require primary-button ruler drags
- Share guide preview types through a neutral editor module
2026-08-19 20:13:57 +03:00
Danila Poyarkov 0abc4cc21b
Merge pull request #547 from 0xemc/feat/combine-as-variants
feat(figma-api): add combineAsVariants for real component variant sets
2026-08-19 20:06:33 +03:00
Danila Poyarkov c05a5596aa fix(tools): require sibling variant components
- Reject combine_as_variants inputs that span different parents\n- Preserve all source components when validation fails\n- Cover the tool-level error path
2026-08-19 20:05:54 +03:00
Danila Poyarkov 1db92c4603 fix(figma-api): align variant combination behavior
- Match the Figma parent and insertion-index API contract\n- Reject duplicate component references before graph mutation\n- Share slash-name variant derivation with editor actions\n- Add structural regression coverage and changelog entry
2026-08-19 20:05:54 +03:00
xemc b01ed830e8 feat(figma-api): add combineAsVariants for real component variant sets
figma.combineAsVariants() was unimplemented in the scripting/automation
layer (figma-api/proxy.ts's compatibility surface), even though the editor
UI already has a full equivalent — createComponentSetFromComponents()
(editor/components.ts) plus wrapSelectionInContainer()
(editor/structure/container-wrap.ts) — wired to the app's own "Create
component set" menu action.

This ports that logic down to FigmaAPI (the class MCP tools, the CLI, and
AI chat scripting all run against): wraps selected COMPONENT nodes sharing
a parent into a COMPONENT_SET, and derives variant property definitions from
"Category/Value" node-name segments, matching the editor behavior exactly.
Drops the undo-stack push and selection-state writes the editor path has,
since neither concept exists at the scripting layer — everything else is
the same primitives (SceneGraph.createNode/insertChildAt/reparentNode),
which FigmaAPI already had direct access to.

Also adds a matching combine_as_variants tool (packages/core/src/tools/
create/components.ts) registered in EXTENDED_TOOLS, so it's exposed
through MCP, the CLI, and AI chat alongside the existing create_component/
create_instance tools.
2026-08-19 20:05:54 +03:00
Danila Poyarkov 4b8bf021f6
Merge pull request #548 from 0xemc/fix/fig-component-property-roundtrip
fix(fig): component properties silently dropped on save
2026-08-19 20:04:57 +03:00
Danila Poyarkov 62ba072b26
refactor(ai): ship Harness as optional companion (#561)
* Revert "feat(ai): add HarnessAgent sidecar foundation (#560)"

This reverts commit 83a5ea1b42.

* Revert "Revert "feat(ai): add HarnessAgent sidecar foundation (#560)""

This reverts commit 0d8c03515888c62dc47186d4a3b0b7b04e78f8af.

* refactor(ai): ship Harness as optional companion

* fix(ai): support Harness companion on Windows

* test(ai): restore navigator after Harness Windows test
2026-08-19 20:04:35 +03:00
Danila Poyarkov e86c4c9b9b Merge remote-tracking branch 'origin/master' into review-pr-548-head 2026-08-19 18:33:16 +03:00
Danila Poyarkov adaf6dacb9 fix(canvas): keep guide renderer fixtures complete 2026-08-19 18:10:36 +03:00
Danila Poyarkov f9c0f56ec3 chore(vue): keep guide input dispatch lint-clean 2026-08-19 18:09:46 +03:00
Danila Poyarkov f892cb583c feat(editor): add ruler guide authoring foundation
- Preserve page and frame guide GUIDs through .fig conversion
- Add undoable guide add, move, transfer, and remove actions
- Start page/frame guide previews from CanvasKit rulers
- Render warm guide previews with frame-scoped solid lines and dotted continuation
2026-08-19 18:08:48 +03:00
Danila Poyarkov 33962b764c fix(fig): harden component property round trips
- Allocate collision-safe property GUIDs across every export path
- Preserve instance-swap component keys and unresolved GUID targets
- Prefer edited assignments over imported raw metadata
- Cover recursive serialization, assignments, and key preservation
2026-08-19 18:05:25 +03:00
Danila Poyarkov 83a5ea1b42
feat(ai): add HarnessAgent sidecar foundation (#560)
* feat(ai): add HarnessAgent sidecar foundation

* feat(ai): integrate Pi as a Harness provider

* fix(ai): harden Harness provider integration

* fix(ai): address Harness integration review

* fix(ai): align Harness code with project conventions

* fix(ai): preserve Harness sessions on cancellation

* test(ai): cover Harness JSONL framing

* refactor(ai): generalize Harness sidecar adapters

* fix(ci): build Harness sidecar for native checks
2026-08-19 17:41:10 +03:00
Danila Poyarkov 8aeda81f3a Merge remote-tracking branch 'origin/master' into review-pr-548-head 2026-08-19 17:27:47 +03:00
Danila Poyarkov 44d9ba477a
Merge pull request #546 from 0xemc/fix/fs-plugin-permissions
fix(desktop): grant missing fs-plugin permissions for exists/read_text_file/create/open
2026-08-19 17:13:57 +03:00
Danila Poyarkov a2161aef63 fix(desktop): narrow MCP discovery permissions
- Limit text reads and existence checks to platform discovery files
- Drop unused create and open capabilities
- Document restored desktop automation reconnection
2026-08-19 16:49:21 +03:00
Danila Poyarkov 733b179e16 Merge remote-tracking branch 'origin/master' into review-pr-546-fix 2026-08-19 16:14:20 +03:00
Danila Poyarkov 0d6f50b445
Merge pull request #559 from open-pencil/feat/configurable-snapping-guides
feat(editor): add configurable snapping and guides
2026-08-19 13:22:24 +03:00
Danila Poyarkov 73f0883521 Merge remote-tracking branch 'origin/master' into feat/configurable-snapping-guides 2026-08-19 13:20:21 +03:00
Danila Poyarkov 8e3f904ed4 fix(io): normalize legacy guide arrays safely
- Restore missing or malformed guides as empty arrays during graph hydration
- Keep library revision clones independent while preserving valid guides
2026-08-19 12:53:00 +03:00
Danila Poyarkov 9ef2f63d57 fix(editor): harden snapping edge cases
- Preserve rounded auto-layout preview displacement through drop commits
- Bound imported layout-guide counts and tiny grid steps
- Normalize missing guide arrays in direct graph hydration paths
- Add regression coverage for auto-layout movement and guide limits
2026-08-19 12:33:32 +03:00
Danila Poyarkov 94d3b28be6 fix(canvas): release vector drags on global mouseup
- Observe window mouseup in capture phase so overlays cannot swallow drag completion
- Assert vector points stop following the pointer after release
2026-08-19 11:05:03 +03:00
Danila Poyarkov 17f791ffe4 fix(vue): guard optional resize test state without lint noise 2026-08-19 10:23:45 +03:00
Danila Poyarkov f4ef46a249 test(vue): keep resize helpers compatible with partial editors 2026-08-19 00:15:34 +03:00
Danila Poyarkov f2228f45ef fix(editor): apply CodeRabbit snapping fixes
- Preserve transformed Control bypass and native preference dispatch
- Clarify snapping settings and keep fractional positions visible
- Filter hidden targets and harden guide and resize handling
- Update native menu schema coverage
2026-08-19 00:07:29 +03:00
Danila Poyarkov b48fe1623b fix(editor): address snapping review feedback after merge
- Preserve transformed Control-bypass movement and hide invalid snap targets
- Route native snapping toggles through persisted preference actions
- Harden axis tolerance, resize behavior, and guide repaint lifecycle
- Keep fractional coordinates visible and clarify localized setting descriptions
2026-08-18 23:12:02 +03:00
Danila Poyarkov 0332b062c5
refactor(canvas): adopt immutable CanvasKit paths (#554)
* refactor(canvas): adopt immutable CanvasKit paths

- Upgrade CanvasKit to 0.41.1 across app, Core, CLI, and Vue peers

- Build mutable geometry with PathBuilder and detach immutable paths for drawing

- Replace in-place strokes, transforms, and boolean operations with immutable results

- Update renderer mocks and path construction tests for the new API

* test(canvas): model immutable path ownership

- Return detached path instances from CanvasKit builder mocks

- Assert shadow ring and combined path disposal

- Preserve recorded vector operations across ownership transfer

* fix(build): align CanvasKit workspace versions
2026-08-18 23:09:45 +03:00
Danila Poyarkov e0491ed0ae Merge remote-tracking branch 'origin/master' into feat/configurable-snapping-guides 2026-08-18 22:57:27 +03:00
Danila Poyarkov d44c1f9d82
ci: parallelize quality and trim shard builds (#558)
* ci: parallelize quality and trim shard builds

- Split source, package, repository, and Storybook checks into independent jobs

- Build only Core before quick unit shards instead of all public packages

- Keep full package and dist validation in the dedicated package-quality job

- Disable duplicate Storybook component metadata extraction

* fix(ci): build declarations before source checks

* fix(ci): apply review security and docgen settings

- Pin checkout and disable credential persistence

- Declare read-only workflow permissions

- Explicitly disable Storybook Vue docgen

* ci: clarify check and step names

* fix(ci): cap workflow job runtimes

- Limit the WebView dependency install to three minutes

- Limit native contracts to eight minutes

- Limit all other CI jobs to ten minutes

* ci: retry native contracts on a fresh runner

* ci: move native contracts to Ubuntu 24

- Leave the deprecated Ubuntu 22 hosted image

- Retry WebKit dependency provisioning on the current runner image

* ci: prebuild native contract dependencies

* ci: pin native contracts image digest

* fix(ci): authenticate native image pulls

* fix(ci): include Bun archive tooling

* ci: pin updated native contracts image

* fix(tools): register CI image tooling
2026-08-18 22:52:18 +03:00
Danila Poyarkov 42b1fa07f0 Merge origin/master into feat/configurable-snapping-guides 2026-08-18 22:05:51 +03:00
Danila Poyarkov 921cd702f8 fix(editor): address snapping review feedback
- Preserve parent-local movement during Control bypass
- Route native snapping menu actions through persisted preferences
- Harden guide alignment, lifecycle rendering, and transformed resize behavior
- Update preference descriptions and fractional position display
2026-08-18 22:03:53 +03:00
Danila Poyarkov bd4f6f0a22
build(ai): upgrade to AI SDK 7 (#555)
- Upgrade direct model chat providers and transports to AI SDK 7.\n- Keep the local ACP execution path unchanged.\n- Preserve chat, tool, vision, and provider behavior across the adapter boundary.
2026-08-18 19:31:02 +03:00
Danila Poyarkov 91e759d7fd feat(editor): add configurable snapping and guides
- Snap vector points, moved layers, and resized edges to geometry, objects, guides, and pixels
- Add persistent snapping preferences with browser and native menu controls
- Normalize canvas and layout guides across Scene Graph and .fig conversion
- Clear transient snapping feedback across interrupted interactions
2026-08-18 19:11:48 +03:00
Danila Poyarkov 211a4ea99c
fix(i18n): localize app notifications (#557)
- Add app-owned notification translations for every supported locale.\n- Localize common file, clipboard, collaboration, chat, vectorization, storage, recovery, and library toasts.\n- Preserve actionable runtime details inside localized messages.
2026-08-18 18:52:19 +03:00
Danila Poyarkov 3e8171ffda docs: clean up Unreleased changelog
- Keep one section per public changelog category

- Remove duplicate and validation-only entries

- Restore missing user-visible clipboard and MCP fixes
2026-08-18 17:54:18 +03:00
Danila Poyarkov f3973202eb
chore: refresh compatible dependencies (#545)
- Refresh compatible workspace dependencies and lockfiles.\n- Preserve package exports and documentation compatibility.\n- Update affected compatibility tests.
2026-08-18 17:44:40 +03:00
Danila Poyarkov 4342fd3262
perf(chat): release completed streaming parser history (#553)
- Keep only the active assistant response in streaming Markdown mode.\n- Remount completed responses in static mode to release incremental AST caches.\n- Preserve final Markdown, code rendering, and theme behavior.
2026-08-18 17:43:49 +03:00
Victor Wads 4e48420ac1
feat(app): open multiple files from the Open dialog (#552)
- Open multiple selected design files in separate tabs.\n- Support desktop, File System Access, and fallback pickers.\n- Continue opening later selections when one file fails.
2026-08-18 11:30:36 +03:00
xemc 783cdf9dbc fix(fig): component property definitions/references/assignments never survive a save/reload round trip
parseGuidOrNull requires the strict Figma GUID shape (sessionID:localID),
but every OpenPencil code path that creates a component property definition
uses `prop:<hex>` IDs, which never match. applyComponentMetadata silently
dropped componentPropDefs/componentPropRefs/componentPropAssignments/
variantPropSpecs whenever any entry failed that check, so any component
property created by the app (as opposed to imported straight from a real
Figma file) vanished on the very next save.

Mint a stable synthetic GUID for non-Figma-shaped property IDs instead of
dropping them, memoized per export so defs/refs/assignments/variantPropSpecs
pointing at the same property stay consistent. Also fix INSTANCE_SWAP
default/preferred/assignment values, which reference target node IDs and
had the same GUID-shape assumption, and were never being resolved back to
real node IDs on import in the first place (remapComponentIds only handled
instance.componentId, not these fields).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-18 08:10:11 +10:00
xemc 3f6cb88b5e fix(desktop): grant missing fs-plugin permissions for exists/read_text_file/create/open
The default capability only granted read_file/write_file/mkdir/remove/watch,
but the app also calls exists(), readTextFile(), create(), and open() from
@tauri-apps/plugin-fs. Each fs-plugin command requires its own explicit
permission identifier in Tauri v2 — these were never added.

The most visible symptom: EditorView's automation startup calls
discoveryFileExists()/readDiscoveryToken() (spawn.ts) to reuse an already-
running MCP server. With allow-exists and allow-read-text-file missing, both
calls silently fail (the fs-plugin IPC rejection is caught and treated as
"file not found"), so the app always falls through to spawning a redundant
MCP server process and registers with a freshly generated auth token instead
of the real one — which the already-running server then rejects, leaving
automation permanently disconnected from any already-running MCP server.
2026-08-18 06:15:12 +10:00