Commit Graph
99 Commits
Author SHA1 Message Date
bflatastic 4565ed9686 Merge main into #2143 2026-11-12 10:06:02 +07:00
BFlat 4531e99e5c Merge pull request #2070 from dotCooCoo/fix/export-color-docs
Export: color profile text states which formats are tagged and that CMYK PDF is DeviceCMYK
2026-11-12 09:56:27 +07:00
Trevor BrownandClaude Opus 5.5 8b15c00f84 M8: the MCP pointer tool lists the Annotation tool (#1840)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove and wrote
2026-11-09 01:22:52 -05:00
FredApps 72cfe7be30 fix(naming): use direct FigCraft feature descriptions (#2131)
Drops the "Figma-class" self-description from the MCP instructions and the "Accessibility at Figma" aside from pref.uiScaleUp help. Help text only; ids and preference keys unchanged. Adds a display-name guard over mcp/src and engine/src/cmd string literals.
2026-11-09 06:22:48 +01:00
dotCooCoo 297426c595 Export: color profile text states which formats are tagged and that CMYK PDF is DeviceCMYK
The export tool and command descriptions, docs/mcp.md and the file-format
table said PDF is always sRGB, that sRGB JPG is untagged and that every
exported file is tagged with its profile. RGB PDF is sRGB and PDF with cmyk
is DeviceCMYK; JPG embeds an ICC profile for sRGB and Display P3; WebP embeds
one for Display P3 only. The JPG quality (1 to 100, default 90) now has one
row in the format table.
2026-11-06 22:21:51 -08:00
bflatastic 02f5a3520a Merge main into #1759 2026-11-07 11:19:38 +07:00
JonRC a55a728c4c M6: JPG exports take a quality and embed the sRGB profile (#2004)
file.export always encoded JPG at quality 90, and an sRGB document's JPGs
carried no colour profile, so viewers could only assume sRGB. PNG exports
always get an sRGB chunk, and Display P3 JPGs already embedded their ICC
profile.

- ExportSetting gets a quality (1 to 100, default 90, saved only when it
  isn't 90), parsed with the other export options: file.export, export.add,
  export.update, file.exportLayers and MCP export take it.
- encode_export_with takes the quality; encode_export keeps quality 90.
  Every JPG now embeds the document's profile, sRGB included.
2026-11-05 00:09:19 -03:00
Dylan M. Taylor f54e099a48 fix(mcp): render prompt placeholders in one pass over the template (#1922)
Each argument was substituted into the already rendered text, so a value
holding placeholders was expanded again by every later replacement and a
short request could grow the prompt without bound. The template is now
scanned once and argument text is never read as syntax.
2026-11-03 22:27:10 -05:00
dotCooCoo afc5e13972 Export: each export setting chooses a color profile
Each export setting has a color profile: Same as file (the default, the
document's profile when it exports), sRGB or Display P3. PNG, JPG and
WebP settings list it in their advanced settings, and export.add,
export.update, file.export, file.exportLayers (for every setting) and
the MCP export tool take it as colorProfile. The rendered pixels are
converted to the chosen profile (out-of-gamut colors clip) and the file
is tagged as before: an sRGB chunk for sRGB PNG, the generated ICC
profile (and cICP in PNG) for Display P3; sRGB JPG and WebP stay
untagged. A setting keeps its choice when its format changes, and
settings saved without one read as Same as file.

SVG, PDF and Android XML show no choice and stay sRGB; PDF has no
output intent yet.
2026-10-31 03:07:17 -07:00
BFlat 3b77c236af Merge pull request #1731 from zral/docs/vector-path-xy-offset
M0.9: document that x/y offset a vector path by its own box
2026-10-31 09:14:25 +07:00
BFlat 437d052396 M8: a control request can set its own timeout, up to 10 minutes (#1696) (#1706)
A request line can carry timeoutMs beside id and method, capped at 600,000 ms; without it the wait stays 60 s and older apps ignore the field. figcraft-cli mcp --attach PORT --timeout SECONDS sends it with every request and reads the answers that much longer. A timeout's message says how long the request waited.
2026-10-31 03:41:56 +07:00
Lars SøraasandClaude Opus 5.5 57f0185f41 M0.9: document that x/y offset a vector path by its own box
node.create / vector.create (and MCP create_node) place a vector made from
SVG path data or points at x/y plus the box's unscaled offset: a path whose
box starts at (30, 0) with x 830 lands at 860. That is deliberate and pinned
by vector_path_set_tests, but the MCP schema described x as the layer's left,
which misled an agent drawing a poster. The x, y and path descriptions and
the node.create / vector.create parameter docs now say so, and an MCP test
pins the placement for path and points, the 0,0 alternative, set_properties
x moving the left edge, and the documentation.

CI: fmt, clippy, layers, assets and wasm pass; every test passes except
board_tables_tests::a_double_click_types_in_the_cell_and_its_row_grows_with_the_text
and clipboard_fence_tests::a_synthetic_copy_shortcut_leaves_the_system_clipboard_alone,
which fail the same way on main without this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 18:12:20 +01:00
BFlat d17de284da Tests: read the docs' examples whatever the checkout's line endings (#1645)
inspect_fields::compact_examples_run_verbatim_from_the_docs split docs/mcp.md and docs/control-protocol.md on text ending in a newline, so on a Windows checkout with core.autocrlf (CRLF docs) it panicked and cargo xtask ci failed locally. The test now reads both with LF line ends. Found while gating on Windows.
2026-10-30 15:53:33 +07:00
Mert Dede 5c3aef840a Merge remote-tracking branch 'origin/main' into feat/996-inspect-fields
# Conflicts:
#	docs/roadmap.md
2026-10-30 07:07:54 +03:00
BFlat bc11197c21 M1: Enter or a double-click with the pen edits the vector with the Move tool (#1430) (#1590)
A double-click with the pen drew on: its second press added a point on the last one, and a double-click meant to edit a layer drew a stray vector on it. A press on the last anchor now adds nothing; a double-click ends the path (or, when it only started one, edits the layer under it) and Enter ends the path, both going on in vector edit mode with the Move tool. In edit mode the pen's Enter and double-click take the Move tool, the double-click taking back what its first press began. Escape still keeps the pen (#760).
2026-10-30 08:41:01 +07:00
Mert DedeandClaude Opus 5.5 42e1a39d72 Merge main into #1420
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 01:47:34 +03:00
BFlat 3af5d8a534 M9: comment.list reports the names each message mentions (#1415) (#1534)
Every message (the first and each reply) gets `mentions`: {name, known,
you} for each @mention, by the rule the thread view highlights with
(figcraft_doc::mentions, now shared with mention_ranges). Names resolve
against the file's people and you; unknown names are kept with
known: false; a@b.com mentions nobody.
2026-10-29 22:07:06 +07:00
BFlat 3108d5bee7 M8: edit.duplicate returns an id map with map: true (#995) (#1528)
With map: true, edit.duplicate also returns map: each original layer's id, descendants included (nested frames, groups, instances and their sublayers), paired with its copy's id, so a batch can edit inside a copy through a step reference instead of inspecting it. Without map the result is unchanged.
2026-10-29 20:34:30 +07:00
BFlat 714bbfcdaa M8: MCP and control calls name the document they act on (#998) (#1533)
Tools that act on a document, and the control methods engine.execute,
document.inspect, node.get and ui.render, take an optional `document`
(an open file's id from doc.list / document.inspect, or its path). The
call acts on that file and the tab in front stays in front, so an
attached agent keeps editing its own file when the user switches tabs.
2026-10-29 19:47:41 +07:00
BFlat 72b4269383 M8: an AI agent attached over MCP comments under its own name (#1414) (#1529)
Every command an MCP client runs acts as the client's name from initialize (clientInfo.title, else .name) with ' (agent)' after it, or 'AI agent' without one, carried to the app as engine.execute {agent}. Its messages, reactions and read state are its own, and its messages are marked (agent: true in the file and comment.list, an Agent label in the thread). The user's name and comments made in the app are unchanged; in live sessions the name and marker travel with the thread.
2026-10-29 19:15:19 +07:00
dd55ef63dd Merge main into #1420
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-29 12:18:33 +03:00
bflatastic e89def2068 Merge main into #1409 2026-10-29 13:46:42 +07:00
BFlat c2c720087c Merge pull request #1408 from avhn/feat/996-node-find
M0.9: find layer ids without changing the selection (#996)
2026-10-29 13:41:43 +07:00
BFlat 3be354d227 Merge pull request #1461 from MortenHusted/fix/open-file-reload
M1: opening a file that is already open says when it changed on disk, and can read it again (#997)
2026-10-29 13:41:21 +07:00
bflatastic c6c11471db Merge main into #1408
# Conflicts:
#	crates/engine/src/cmd/edit.rs
#	docs/roadmap.md
2026-10-29 12:23:48 +07:00
bflatastic c5ba6dd2e8 Merge main into #1409
# Conflicts:
#	crates/engine/src/session/undo.rs
#	docs/roadmap.md
2026-10-29 12:23:11 +07:00
bflatastic d1e96ea706 Merge main into #1461 2026-10-29 12:22:30 +07:00
bflatastic a51e815073 Merge main into #1460 2026-10-29 12:22:28 +07:00
bflatastic 49a41cddd4 Merge main into #1408
# Conflicts:
#	docs/roadmap.md
2026-10-29 11:40:48 +07:00
bflatastic 1505681a54 Merge main into #1407 2026-10-29 11:39:50 +07:00
bflatastic 56196eac5a Merge main into #1409
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/session/undo.rs
#	docs/roadmap.md
2026-10-29 11:27:45 +07:00
bflatastic f154011299 Merge main into #1461 2026-10-29 11:19:05 +07:00
bflatastic f99f01d57b Merge main into #1460 2026-10-29 11:09:30 +07:00
bflatastic fd81433a23 #1460: text.style lists the text-decoration and variation keys the Typography panel sends, paragraph spacing on selected characters goes to node.set, MCP builds its tool catalogue once, and a test for the params panels build 2026-10-29 11:09:09 +07:00
phonedu 8e6b3bf449 M12: MCP comment feedback and live change events
Comments become the task queue for an attached or headless MCP client: comment.prompt returns a bounded Markdown brief, the Comments panel gains Copy for AI, and the MCP server exposes fix_comments, watch_comments, figcraft://comments and wait_for_changes. Mutating comment.* commands append to a bounded in-memory event log; the control channel's events.poll long-polls it without the UI thread, and a successful batch commits its events only if the whole batch lands. No model, network dependency, asset or file-format change.
2026-10-28 21:42:31 +08:00
MortenHustedandClaude Opus 5.5 3567bef862 #1460: commands and tools that pass their params on list what they pass
file.placeImage runs image.place's code and file.exportSvg file.export's,
so their docs now list the names those read (width, height, target, mode;
scale or size and the export options). MCP's create_node passes points,
closed and select to node.create, and pointer and key read ctrl, so their
schemas list them too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:35:23 +01:00
MortenHustedandClaude Opus 5.5 40b9288f70 M1: opening a file that is already open says when it changed on disk, and can read it again
`file.open` on a path already open in a tab switched to it and returned
its index, even when another process had changed the file since, so the
caller kept looking at the old copy with nothing saying so (#997). The
tab's disk stamp from #1330 (`DocState::on_disk`) now tells:

- the result says `stale: true` when the file on disk differs from what
  the tab read or last saved;
- `reload: true` reads the file again into the tab, as Revert to saved
  does (refused while the tab has unsaved changes or is in a live
  session), and the result says `reloaded: true`.

MCP's `open_file` takes `reload` and passes it on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:19:56 +01:00
MortenHustedandClaude Opus 5.5 27c11858e1 M0.9: MCP tools and batch steps refuse names they don't take (#1413)
`run_command {"command": "inspect.code", "args": {...}}` ran the command
without its params, on the selection. MCP tool arguments are now checked
against each tool's input schema (and the objects it describes inside,
such as a batch's steps; open objects like `params` take anything), and
a step key other than `command`, `params` and `as` is refused in
command.batch, figcraft-cli scripts and the MCP batch tool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:06:59 +01:00
d86a7ad9d9 M0.9: inspect layer trees with selected fields or a compact outline (#996)
node.get, the control channel's inspect methods and the MCP get_node / inspect_document tools
take fields: [node keys], applied at every level, or outline: true (id, name, type, characters
cut to 120 characters, mainComponentName, visible). Ids and structure are always kept, properties
that aren't selected aren't computed, and the default output is unchanged. Part of #996.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-27 12:55:47 +03:00
300a5f2f9d M0.9: let batches continue after failed steps (#1386)
command.batch and the MCP batch tool take onError: "abort" (the default, unchanged) or
"continue". In continue mode each step runs inside a rollback-only checkpoint split out of
Session::grouped: a failed step is rolled back on its own, later steps still run, and the result
is one {step, command, ok, result|error} object per step. What was applied is one undo step; a
reference to a failed step fails too; malformed batches are still rejected before any step runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-27 07:57:54 +03:00
57c1133a34 M0.9: find layer ids without changing the selection (#996)
node.find {root?, name?, type?, text?, component?, limit?} returns {ids, total} for the strict
descendants of root (or the current page) that match every filter given: name, text and main
component name as case-insensitive substrings, type as an exact type name. It changes neither the
selection, the page nor the undo history. Part of #996; fields/outline are left for later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-27 07:57:54 +03:00
8ae76d9b2a M8: bound attached MCP replies to 512 MiB (#1113)
The attached backend read each reply from the app's control port with read_line, which has no
limit. It now reads up to 512 MiB before the newline (an app window capture is at most 256 MiB as
base64) and stops at the first byte past that. An oversized or non-UTF-8 reply drops the
connection and is reported like a lost reply; the next call reconnects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-27 07:57:53 +03:00
BFlat cac54fd552 Merge pull request #840 from StrajnarFilip/feat/vector-drawable-export
M6: export as Android Vector Drawable (XML)
2026-10-27 01:06:21 +07:00
bflatastic de826e14cf Merge main into #650
# Conflicts:
#	crates/ui-egui/locales/es.toml
#	crates/ui-egui/locales/pl.toml
#	docs/prototyping-parity.md
2026-10-26 23:24:22 +07:00
bflatastic c208ae442c #840: move the CLI and MCP XML export tests into tests/it 2026-10-26 23:23:08 +07:00
bflatastic e469cc8135 Merge main into #840
# Conflicts:
#	apps/figcraft-cli/src/files.rs
#	apps/figcraft-cli/src/main.rs
#	crates/engine/src/cmd/file.rs
#	crates/engine/src/lib.rs
#	crates/ui-egui/locales/en.toml
#	crates/ui-egui/locales/es.toml
#	crates/ui-egui/src/export_panel.rs
#	crates/ui-egui/src/export_preview_tests.rs
#	docs/file-format-parity.md
#	docs/mcp.md
#	docs/roadmap.md
#	docs/ui-parity.md
2026-10-26 23:23:07 +07:00
bflatastic 07a654959a Merge main into #1021
# Conflicts:
#	docs/file-format-parity.md
2026-10-26 09:12:39 +07:00
BFlat 09d2d96588 Merge pull request #1353 from storytold/fix/sonar-new-code-refactor
refactor: clear SonarCloud new-code issues (S3776, S107) and exclude generated coverage tree
2026-10-26 09:04:36 +07:00
Dylan M. Taylor 7dc5d3b377 refactor(mcp): group with_marker's cut sizes into a struct (SonarCloud S107)
The depth and wire-size numbers describing a cut subtree are now one Cut
value, so with_marker takes 5 parameters instead of 8. Output is unchanged.
2026-10-25 21:11:43 -04:00
Jindřich ŠaršonandClaude Opus 5.5 b8c120f30c M6: Sketch import: name .sketch in the file.open, file.import and MCP open_file docs
The command parameter docs (CLI `commands`, MCP list_commands, the Actions
palette) and the MCP open_file tool description listed .fig but not
.sketch; docs/mcp.md and docs/cli.md already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:33:22 +01:00