@pixerate/editor 0.80.0 → 0.81.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +13 -3
  2. package/dist/agent/index.cjs +102 -6
  3. package/dist/agent/index.cjs.map +1 -1
  4. package/dist/agent/index.d.cts +4 -2
  5. package/dist/agent/index.d.ts +4 -2
  6. package/dist/agent/index.js +101 -5
  7. package/dist/agent/index.js.map +1 -1
  8. package/dist/{builtins-BKYlHH1s.d.ts → builtins-CV1fDj64.d.ts} +5 -1
  9. package/dist/{builtins-1kqwLUnb.d.cts → builtins-c4w0eAYl.d.cts} +5 -1
  10. package/dist/{chunk-2CJ3LPYQ.js → chunk-424H3P4I.js} +13 -295
  11. package/dist/chunk-424H3P4I.js.map +1 -0
  12. package/dist/{chunk-UN33YOXW.cjs → chunk-PA5S7KPC.cjs} +293 -2
  13. package/dist/chunk-PA5S7KPC.cjs.map +1 -0
  14. package/dist/{chunk-IB3ZHQAX.js → chunk-PTYWCFFW.js} +29 -4
  15. package/dist/chunk-PTYWCFFW.js.map +1 -0
  16. package/dist/{chunk-JQ3BB3E6.js → chunk-PXDEFEG2.js} +293 -2
  17. package/dist/chunk-PXDEFEG2.js.map +1 -0
  18. package/dist/{chunk-YU4WQE5M.cjs → chunk-TAPXWP2B.cjs} +95 -377
  19. package/dist/chunk-TAPXWP2B.cjs.map +1 -0
  20. package/dist/{chunk-HXDMZQTD.cjs → chunk-TPOT575P.cjs} +29 -4
  21. package/dist/{chunk-IB3ZHQAX.js.map → chunk-TPOT575P.cjs.map} +1 -1
  22. package/dist/commands/index.cjs +2 -2
  23. package/dist/commands/index.d.cts +1 -1
  24. package/dist/commands/index.d.ts +1 -1
  25. package/dist/commands/index.js +1 -1
  26. package/dist/generation/index.cjs +932 -791
  27. package/dist/generation/index.cjs.map +1 -1
  28. package/dist/generation/index.d.cts +266 -240
  29. package/dist/generation/index.d.ts +266 -240
  30. package/dist/generation/index.js +926 -785
  31. package/dist/generation/index.js.map +1 -1
  32. package/dist/image-editor/index.cjs +266 -2
  33. package/dist/image-editor/index.cjs.map +1 -1
  34. package/dist/image-editor/index.d.cts +12 -1
  35. package/dist/image-editor/index.d.ts +12 -1
  36. package/dist/image-editor/index.js +265 -1
  37. package/dist/image-editor/index.js.map +1 -1
  38. package/dist/index.cjs +3 -3
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.js +16 -16
  41. package/dist/spreadsheet/index.cjs +3 -3
  42. package/dist/spreadsheet/index.cjs.map +1 -1
  43. package/dist/spreadsheet/index.js +16 -16
  44. package/package.json +2 -1
  45. package/skills/README.md +55 -0
  46. package/skills/pixerate-agent-tools/SKILL.md +75 -0
  47. package/skills/pixerate-animation-editor/SKILL.md +155 -0
  48. package/skills/pixerate-animation-editor/references/commands.md +123 -0
  49. package/skills/pixerate-canvas/SKILL.md +230 -0
  50. package/skills/pixerate-chart/SKILL.md +190 -0
  51. package/skills/pixerate-diagram/SKILL.md +134 -0
  52. package/skills/pixerate-generation/SKILL.md +109 -0
  53. package/skills/pixerate-image-editor/SKILL.md +139 -0
  54. package/skills/pixerate-parameters/SKILL.md +83 -0
  55. package/skills/pixerate-rich-text/SKILL.md +160 -0
  56. package/skills/pixerate-spreadsheet/SKILL.md +146 -0
  57. package/skills/pixerate-vector/SKILL.md +191 -0
  58. package/skills/pixerate-vector/references/commands.md +138 -0
  59. package/skills/pixerate-video-editor/SKILL.md +173 -0
  60. package/dist/chunk-2CJ3LPYQ.js.map +0 -1
  61. package/dist/chunk-HXDMZQTD.cjs.map +0 -1
  62. package/dist/chunk-JQ3BB3E6.js.map +0 -1
  63. package/dist/chunk-UN33YOXW.cjs.map +0 -1
  64. package/dist/chunk-YU4WQE5M.cjs.map +0 -1
@@ -0,0 +1,190 @@
1
+ ---
2
+ name: pixerate-chart
3
+ description: How to build, edit and check charts in the Pixerate chart editor through its agent tools and chart.* commands - bar, column, line, area, scatter, bubble, pie, donut, radar, waterfall, histogram, box plot, funnel and treemap charts; series, categories, stacking, secondary axis, log axis, number formats, data labels, legend, trendline, error bars, colour palettes and colour-blind checks, CSV and Mermaid import, Office chart XML export, and reading charts out of open .xlsx, .pptx and .docx files. Use when a chart editor's tools (get_chart, update_chart, set_chart_values, list_file_charts...) are available or the user asks to make, restyle, fix or explain a chart.
4
+ ---
5
+
6
+ # Charts
7
+
8
+ A chart editor holds one `ChartSpec`: a `type`, `title` / `subtitle`, `xAxis` / `yAxis` /
9
+ `yAxis2`, `legend`, presentation fields (stacking, orientation, curve, data labels, palette),
10
+ a list of `categories` (strings, in order) and a list of `series`. Each series has an `id`
11
+ (such as `series-1`), a `name` and one value per category (`null` is a gap), plus optional
12
+ per-series settings (type for combos, secondary axis, marker, colour, format, trendlines,
13
+ error bars). Tools take a series by id or exact name and a category by 0-based index or
14
+ exact label; `get_chart` returns both. Pie, donut, funnel and treemap draw only the first
15
+ visible series, one slice per category; histogram and box read every value of the visible
16
+ series.
17
+
18
+ Read `pixerate-agent-tools` first for tool naming, errors and `run_commands` batching.
19
+ Charts inside a rich-text document are not edited with these tools: use `insert_chart`,
20
+ `list_document_charts` and `update_chart_in_document` from the `pixerate-rich-text` skill
21
+ (a chart block goes in the prose, never inside a table row).
22
+
23
+ ## Working method
24
+
25
+ 1. **Read.** `get_chart` returns the spec, the data as a table, the selection and a
26
+ summary at the given size (default 640 x 400): per-series min / max / mean / trend, the
27
+ axes as drawn, layout warnings, a colour check and a plain-language description. If the
28
+ data comes from a file, start with `list_open_files` and `list_file_charts`.
29
+ 2. **Choose the form.** Decide what question the chart answers, then call `recommend_chart`
30
+ (on the current data or on CSV you are about to import) and pick from its list.
31
+ 3. **Load data in one call.** Use `import_chart_csv` (with `chartType: "auto"` for a fresh
32
+ chart) or `set_chart_data` for whole tables, `set_chart_values` for individual cells.
33
+ Avoid adding categories and series one by one when you already have the table.
34
+ 4. **Style in one call.** Put type, titles, axes, legend, stacking and labels in a single
35
+ `update_chart`; it is all-or-nothing and one undo step. Use `apply_chart_preset` for a
36
+ coherent layout or colour scheme, `update_chart_series` for per-series settings.
37
+ 5. **Check.** Read the `warnings` that `get_chart` and `render_chart` return (hidden or
38
+ thinned labels, crowded legend, skipped values) and run `check_chart_colors`. Fix every
39
+ problem.
40
+ 6. **Look once.** `render_chart` with `format: "png"` after a batch of edits, at the size
41
+ the chart will be shown, to check overlap and legibility. Use `undo_chart` for your own
42
+ mistakes.
43
+
44
+ ## Best practices
45
+
46
+ - **Pick the type by the question.** Comparison across categories: bar (horizontal with
47
+ `orientation: "horizontal"` for long labels or many categories). Change over time: line
48
+ (area when volume matters; set `xAxis.kind: "date"` for date categories). Composition:
49
+ stacked bar or `stacking: "percent"` for shares across groups; pie or donut only for one
50
+ whole with few parts. Distribution: histogram (`bins`, default the square root of n) or
51
+ box. Relationship: scatter with `series.x`, bubble with `sizes` for a third measure.
52
+ Running totals and bridges: waterfall (`showTotal`). Staged drop-off: funnel.
53
+ - **Bars start at zero.** Bar length encodes the value, so never set a non-zero `min` on the
54
+ value axis of a bar, column or area chart. Line and scatter charts may zoom to the data
55
+ range when the change, not the magnitude, is the point.
56
+ - **Pie and donut: at most about five slices**, all positive, adding up to a meaningful
57
+ whole. Beyond that, use a sorted bar chart or merge small slices into "Other".
58
+ - **Sort bars** by value (largest first) unless the categories have a natural order (time,
59
+ ranks, age bands). Reorder by sending the sorted table through `set_chart_data`.
60
+ - **Limit colours.** Keep to about seven distinct series colours; beyond that, split into
61
+ small multiples or highlight one series and grey the rest (`color`, `pointColors`).
62
+ Run `check_chart_colors` after any palette change; the `okabe-ito` scheme in
63
+ `apply_chart_preset` stays distinct with colour-blindness. Do not encode meaning by
64
+ colour alone: add labels or markers (`marker`).
65
+ - **Label directly.** With few series or few bars, prefer data labels (`dataLabels`,
66
+ `labelPosition: "auto"` drops labels that do not fit) and the `labelled` or `minimal`
67
+ layout over a legend plus grid. Always set a title that states the takeaway and axis
68
+ titles with units.
69
+ - **Number formats.** Set `format` on the axis (and on series labels when they differ):
70
+ `style: "percent"` (0.25 shows as 25%), `"currency"` with `currency`, `"compact"` (1.2K),
71
+ fixed `decimals`, or a spreadsheet `code` such as `#,##0.0,,"M"`. Use the same format on
72
+ the axis and the labels; avoid more decimals than the data justifies.
73
+ - **Honest dual axes.** Use `axis: "secondary"` only when two series have different units,
74
+ title both axes with those units, and make the series visibly different (bar plus line
75
+ via the series `type`). Never use a second axis to make two same-unit series look
76
+ correlated.
77
+ - **Log scale** (`scale: "log"`) only for data spanning orders of magnitude or for growth
78
+ rates; say so in the axis title. It skips values of 0 or less and refuses percent
79
+ stacking.
80
+ - **Trendlines are models, not data.** Add one only when a fit is meaningful, show R2
81
+ (`showR2`) and read it with `get_chart_trendline` before describing the trend; label any
82
+ `forward` forecast as a projection. Exponential, power and log fits need positive values;
83
+ category charts fit against x = 1, 2, 3.
84
+ - **Error bars:** say what they are (standard deviation, standard error, confidence) in the
85
+ title or subtitle.
86
+
87
+ ## Tool reference
88
+
89
+ ### Read
90
+
91
+ | Tool | Use it to |
92
+ | --- | --- |
93
+ | `get_chart` | Start here. Returns spec, data table, selection, issues and a summary (min / max / mean / trend, axes as drawn, layout warnings, colour check, description) at `width` x `height` px (default 640 x 400). Also says why when the chart is read-only. Cheaper than rendering. |
94
+ | `render_chart` | Draw without changing anything: SVG text by default, or `format: "png"` for an image (only when the host can rasterize; otherwise it fails and says to use SVG). Returns the layout warnings too. Images cost tokens: render after a batch of edits, at the display size, to check overlapping or cut-off labels, a crowded legend and unreadable colours. |
95
+ | `check_chart_colors` | Check the chart's series (or slice) colours, or a `colors` list, for normal vision, protanopia, deuteranopia and tritanopia, and contrast against `surface` (default white). Returns the closest pair per vision and problems as sentences. Run after any colour change. |
96
+ | `recommend_chart` | Ranked chart types with a reason each, from `csv` when given, else the current data (series count, points, dates, negative values). Use before choosing a type. |
97
+ | `get_chart_trendline` | Read a trendline's fit (`series`, `index`): coefficients, R2, equation and point count, or the moving-average points. Fails when the fit needs more or positive values. |
98
+ | `list_chart_presets` | List the quick layouts (`standard`, `minimal`, `labelled`, `legend-right`, `presentation`, `analysis`) and colour schemes (such as `default`, `okabe-ito`, `office`, monochrome) with what each changes. |
99
+ | `export_chart_mermaid` | Get the chart as Mermaid `xychart-beta`, `pie` or `radar-beta` for Markdown or chat. With `meta` (default true) a `%% @pixerate` comment keeps everything Mermaid cannot express so `import_chart_mermaid` restores it exactly. |
100
+ | `export_chart_ooxml` | Get a DrawingML `c:chartSpace` part for Word or PowerPoint, plus sentences for anything that could not be written. |
101
+ | `list_open_files` | List the Office files the user opened (name, size in bytes). Only registered when the host shares open files; otherwise the file tools take the whole file as base64 `data`. |
102
+ | `list_file_charts` | List every chart in an `.xlsx`, `.pptx` or `.docx` (`file` name or base64 `data`) in file order: id (such as `chart-1`), place (sheet and anchor cell, or slide number), title, type, series names, category count, read problems, unsupported features and whether it reads losslessly. |
103
+ | `get_file_chart` | Return one file chart's full spec (`file` or `data`, `chartId` from `list_file_charts`) with its place and read problems, without touching the editor. Data comes from the chart's cached values, not the embedded workbook. |
104
+
105
+ ### Write
106
+
107
+ Write tools are hidden while the chart is read-only. Each is one undo step and returns what
108
+ it changed.
109
+
110
+ | Tool | Use it to |
111
+ | --- | --- |
112
+ | `update_chart` | Change presentation in one all-or-nothing call: `type`, `title`, `subtitle`, `xAxis` / `yAxis` / `yAxis2` (show, title, min, max, step, gridlines, format, kind `"date"`, scale `"log"`, logBase, reverse), `legend` (show, position top / bottom / left / right), `stacking` (none / stacked / percent), `orientation`, `curve`, `points`, `dataLabels`, `labelPosition`, `palette`, `innerRadius` (donut hole, 0-0.9), `gapWidth`, `overlap`, `bins`, `showTotal`. Invalid values change nothing and come back as sentences. Returns the spec. |
113
+ | `set_chart_data` | Replace `categories` and / or all `series` (each with `name`, `values` and optional settings). Values are padded with gaps to the categories. Use for whole tables and for re-sorting. Returns the table and series ids. |
114
+ | `set_chart_values` | Set individual `cells` (`series`, `category`, `value`) all-or-nothing. Values may be numbers, numeric text (`"1,200"`, `"12%"`, `"$40"`, `"(3)"`) or `null` for a gap. Returns the stored values. Acted out with a cursor when the host has a director. |
115
+ | `add_chart_series` | Add a series (`name` required; `values`, `color`, `type` for a combo, `axis: "secondary"`, `x` / `sizes` for scatter and bubble, marker, format, error bars, `id`, `at`). Selects it and returns its id. |
116
+ | `update_chart_series` | Rename, recolour, hide, move to the secondary axis, change `type`, `marker`, `curve`, `dataLabels`, `format`, `x`, `sizes`, `pointColors`, `errorBars` / `xErrorBars` of one series; `null` resets a field. Values change with `set_chart_values`. |
117
+ | `remove_chart_series` | Delete a series and its values. Returns the remaining series ids. |
118
+ | `add_chart_category` | Insert a category (`label`, `at`; default the end) as a gap in every series. Returns its index; fill it with `set_chart_values`. |
119
+ | `remove_chart_category` | Delete a category (index or label) and its value in every series. |
120
+ | `import_chart_csv` | Replace the data with CSV or TSV text. Default: first row series names, first column categories (`seriesIn`, `header` change that). `chartType: "auto"` also picks the recommended type (two unlabelled numeric columns become a scatter). Returns the table, the type and cells that were not numbers. |
121
+ | `import_chart_mermaid` | Replace the chart with Mermaid `xychart-beta`, `pie` or `radar-beta` text (fenced or bare). Unreadable lines are skipped and listed with line numbers. |
122
+ | `import_chart_ooxml` | Replace the chart with a raw Office chart part (`c:chartSpace` or chartex XML). Only listed when the host has a `DOMParser` (every browser does). Prefer `load_file_chart` when you have the whole file. |
123
+ | `load_file_chart` | Replace the editor's chart with one from an Office file (`file` or `data`, `chartId`). Returns the spec, read problems and the features the editor could not keep; tell the user about any. |
124
+ | `add_chart_trendline` | Fit a trendline to a series (`type`: linear, exponential, logarithmic, power, polynomial with `order` 2-6, moving-average with `period`; `forward` / `backward` in x units, `intercept`, `showEquation`, `showR2`). Unstacked bar, line, area, scatter and bubble charts only. Returns its index, coefficients, R2 and equation. |
125
+ | `remove_chart_trendline` | Delete a trendline by `series` and `index`. |
126
+ | `apply_chart_preset` | Apply a quick `layout` and / or a `colors` scheme from `list_chart_presets` in one step. |
127
+ | `transpose_chart` | Swap series and categories. Drops per-series colours and settings, so restyle afterwards. |
128
+ | `select_chart_element` | Select part of the chart (`kind`: none, chart, title, subtitle, legend, axis, series, point, category, trendline) for the user to see or before `press_chart_key`. |
129
+ | `drag_chart_point` | Drag a bar or point as the mouse would, with the same snapping (`fine` = Alt, `lockAxis` = Shift on scatter). Positions are 0-1 fractions of the chart at `width` x `height`; use `render_chart` to find marks. Prefer `set_chart_values` for exact numbers. |
130
+ | `press_chart_key` | Send a key to the selection: ArrowLeft / ArrowRight move between categories, ArrowUp / ArrowDown change the value by a tenth of a tick (`shift` a whole tick, `alt` a hundredth), Delete / Backspace remove, Escape clears. |
131
+ | `undo_chart` | Undo the last chart edit. Returns the label of what was undone and the next undo. |
132
+ | `redo_chart` | Redo the last undone chart edit. |
133
+
134
+ ## Commands
135
+
136
+ The `chart.*` commands (run with `run_command` / `run_commands`) mirror the tools. Prefer
137
+ the dedicated tool: it has a stricter schema and returns more (`get_chart` adds the
138
+ selection and read-only reason; `import_chart_csv` has `chartType: "auto"`;
139
+ `check_chart_colors` takes colours and a surface). Use the commands inside an atomic
140
+ `run_commands` batch when chart edits must roll back together with other edits, and for the
141
+ two operations without a tool: `chart.exportSvg` and its fixed-size accessible SVG. Hosts with
142
+ several charts may register them with another prefix.
143
+
144
+ | Command | Use it to |
145
+ | --- | --- |
146
+ | `chart.describe` | Read spec, data table and summary (as `get_chart`). |
147
+ | `chart.update` | Change presentation (as `update_chart`). |
148
+ | `chart.setData` | Replace categories and series (as `set_chart_data`). |
149
+ | `chart.setValues` | Set individual values (as `set_chart_values`). |
150
+ | `chart.addSeries` | Add a series; returns its id (as `add_chart_series`). |
151
+ | `chart.updateSeries` | Change a series' settings (as `update_chart_series`). |
152
+ | `chart.removeSeries` | Delete a series by id or name. |
153
+ | `chart.addCategory` | Insert a category at `at` (default the end). |
154
+ | `chart.removeCategory` | Delete a category by index or label. |
155
+ | `chart.addTrendline` | Fit a trendline (as `add_chart_trendline`). |
156
+ | `chart.removeTrendline` | Delete a trendline. |
157
+ | `chart.applyPreset` | Apply a quick layout and / or colour scheme. |
158
+ | `chart.transpose` | Swap series and categories. |
159
+ | `chart.importCsv` | Replace data from CSV / TSV (no automatic chart type). |
160
+ | `chart.importMermaid` | Replace the chart from Mermaid chart text. |
161
+ | `chart.exportMermaid` | Get Mermaid text (with the round-trip comment unless `meta` is false). |
162
+ | `chart.exportOoxml` | Get the DrawingML chart part. |
163
+ | `chart.exportSvg` | Get a standalone, accessible SVG (title and desc) at `width` x `height` (default 640 x 400), for saving or embedding. |
164
+ | `chart.recommend` | Suggest chart types for the data or `csv`. |
165
+ | `chart.checkColors` | Check the chart's own series colours (no parameters). |
166
+ | `chart.undo` | Undo the last chart edit. |
167
+ | `chart.redo` | Redo the last undone chart edit. |
168
+
169
+ ## Pitfalls
170
+
171
+ - Series values are positional: one value per category, in category order. After
172
+ `add_chart_category` or `remove_chart_category`, every series shifts with it.
173
+ - `set_chart_data` with only `series` keeps the categories; with only `categories` it keeps
174
+ the series, whose values stay matched by position. Pass both to replace a table.
175
+ - Non-numeric cells are refused by `set_chart_values` ("Nothing was changed"); CSV import
176
+ keeps going and lists them in `issues`. Check that list.
177
+ - Percent-stacked charts, pies and gaps cannot be dragged; use `set_chart_values`.
178
+ - Radar needs at least three categories (it draws as a line chart until then); trendlines
179
+ are refused on stacked charts, pies and the other single-series families.
180
+ - `transpose_chart` and `load_file_chart` drop or replace styling; restyle and re-check
181
+ colours afterwards.
182
+ - A `%% @pixerate` comment is what makes Mermaid round-trip exactly. Keep it when the text
183
+ is going back into a Pixerate editor; pass `meta: false` only for plain Mermaid readers.
184
+ - File charts are read from cached values; if the user edited the workbook without saving
185
+ the chart cache, the numbers can be stale. Say so when it matters.
186
+ - An atomic `run_commands` batch only rolls back chart edits when the host shares one history
187
+ between the command registry and the chart; if a batch is refused for that, use the tools
188
+ one by one and `undo_chart`.
189
+ - When the chart is read-only, only the read tools are listed and `get_chart` returns the
190
+ reason. Tell the user; do not try to edit around it.
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: pixerate-diagram
3
+ description: How to build and edit Mermaid diagrams in the Pixerate diagram editor through its agent tools - flowchart, state, class, ER, sequence, Gantt, pie, mindmap, quadrant, C4, architecture, gitGraph, timeline, journey, XY and radar diagrams; adding, connecting, renaming, reshaping and styling nodes, edge labels, subgraphs and groups, layout direction (LR, TB), node and edge data fields, titles, canvas positions, finding Mermaid in Markdown, and rendering to check the result. Use when diagram tools (get_diagram, add_diagram_node, load_diagram_mermaid...) are available or the user asks for a flowchart, process map, state machine, sequence diagram, org or architecture diagram in Mermaid.
4
+ ---
5
+
6
+ # Mermaid diagrams
7
+
8
+ The diagram editor holds one Mermaid document. Its text is the source of truth: every edit
9
+ rewrites only the statements it touches, and untouched statements, comments, directives and
10
+ formatting round-trip byte for byte. Canvas positions live in one `%% @pixerate {...}`
11
+ comment that Mermaid ignores.
12
+
13
+ `get_diagram` describes the document as a graph: the `family` (flowchart, state, class, er,
14
+ pie, mindmap, quadrant, c4, architecture, sequence, gitGraph, gantt, timeline, journey,
15
+ xychart, radar), `direction`, `title`, `nodes` (Mermaid ids such as `A` or `n3`, label,
16
+ shape, `parentId`), `edges` (ids such as `L_A_B_0`, source, target, label), `groups`
17
+ (subgraphs, composite states, namespaces, sections, boxes, boundaries), the `shapes` the
18
+ family allows, its data `fields` and current `settings`. Non-graph families map onto the
19
+ same model: a pie slice, Gantt task, quadrant point or sequence participant is a node
20
+ whose values live in `data`. Sankey, block, packet, kanban and treemap are kept as text
21
+ only (`editable: false`): change them with `load_diagram_mermaid`.
22
+
23
+ Read `pixerate-agent-tools` first for tool naming, errors and batching. Data charts (bar,
24
+ line, pie with styling, trendlines) belong in the chart editor (`pixerate-chart`); Mermaid
25
+ `xychart-beta`, `pie` and `radar-beta` text can move between the two.
26
+
27
+ ## Working method
28
+
29
+ 1. **Read.** `get_diagram` (with `includeSource: true` when you need the text). Note the
30
+ family, the ids, the allowed `shapes` and `fields`. For Mermaid in a user's Markdown or
31
+ chat, `find_mermaid_diagrams` first.
32
+ 2. **Plan the structure** before writing: the family, the flow direction, the nodes and
33
+ their kinds, the groups. Sketch it as Mermaid in your head.
34
+ 3. **Write.** For a new diagram or a rewrite, send the whole text once with
35
+ `load_diagram_mermaid`. For changes to an existing diagram, use the per-operation tools
36
+ (`add_diagram_node` with `from` to add and connect in one call, `rename_diagram_node`,
37
+ `connect_diagram_nodes`...): they keep the user's formatting and comments.
38
+ 4. **Check.** Read the returned ids and any `diagnostics`; fix parse problems before going
39
+ on.
40
+ 5. **Look.** `render_diagram` (`format: "png"` when offered) after a batch of edits to
41
+ check crossings, crowding and label length. Undo your own mistakes with `undo_diagram`.
42
+
43
+ ## Best practices
44
+
45
+ - **Choose the family by the question.** Process or decision logic: flowchart. Lifecycle of
46
+ one thing with events: state. Messages between parties over time: sequence. Data model:
47
+ ER (tables and cardinality) or class (types and methods). Schedule: Gantt. System context
48
+ and containers: C4 or architecture. Brainstorm or hierarchy: mindmap. Two-axis
49
+ prioritisation: quadrant. History: timeline or gitGraph. Numeric series: the chart editor.
50
+ - **One direction, matched to the content.** `LR` for processes and pipelines read like a
51
+ sentence; `TB` for hierarchies and decision trees. Set it once (`set_diagram_direction`);
52
+ do not mix directions except per-subgraph when a group is clearly separate.
53
+ - **Concise labels.** Verb phrases for steps ("Validate order"), noun phrases for things,
54
+ short questions for decisions ("Paid?"), at most five or six words. Put conditions on the
55
+ edges leaving a decision ("yes" / "no"), not in the node. Stable short ids (`validate`,
56
+ `paid`) beat `A`, `B`, `C` when the user will read the source.
57
+ - **Consistent shape semantics.** In flowcharts: `rounded` or `stadium` for start and end,
58
+ `rect` for steps, `diam` for decisions, `cyl` for data stores, `doc` for documents,
59
+ `subproc` for a call into another process, `lean-r` / `lean-l` for input and output. Use
60
+ each shape for one meaning only. In state diagrams use `choice`, `fork` and `join` for
61
+ branching and concurrency.
62
+ - **Group to reduce noise.** Put related nodes in a subgraph (`group_diagram_nodes`) by
63
+ owner, system or phase (swimlane style); keep to one or two levels of nesting.
64
+ - **Limit crossings and fan-out.** Keep each node to a few edges; order statements so the
65
+ main path runs straight; split very large diagrams (more than about 20-30 nodes) into an
66
+ overview plus detail diagrams rather than one dense graph. Every node should be reachable;
67
+ remove orphans.
68
+ - **Style sparingly.** `set_diagram_node_style` to highlight the one or two nodes the
69
+ reader should look at (the error path, the changed step), not to decorate every node.
70
+ Keep enough contrast between fill and text, and do not rely on colour alone.
71
+ - **Title it** (`set_diagram_title`) with what the diagram shows.
72
+
73
+ ## Tool reference
74
+
75
+ ### Read
76
+
77
+ | Tool | Use it to |
78
+ | --- | --- |
79
+ | `get_diagram` | Start here. Returns family, editable flag, direction, title, nodes, edges, groups, allowed shapes, settings, data fields (`fields.node`, `fields.edge`, `fields.diagram` with types and ranges), stored positions, parse diagnostics, the selection and the read-only reason. `includeSource` (default false) adds the Mermaid text. |
80
+ | `export_diagram_mermaid` | Get the Mermaid text to hand back to the user or paste into Markdown. `withLayout` (default true) keeps the `%% @pixerate` positions comment; pass false for plain Mermaid. |
81
+ | `find_mermaid_diagrams` | Find every Mermaid diagram in a piece of `text` (fenced ```mermaid blocks, a chat reply or a bare diagram). Returns each source, family and title; pass one source to `load_diagram_mermaid`. Changes nothing. |
82
+ | `render_diagram` | Draw the diagram without changing it: SVG text by default, `format: "png"` when the host can rasterize; `maxWidth` / `maxHeight` fit it in px. Only listed when the host can render. Refuses text-only families. Render after a batch of edits, not after each one. |
83
+
84
+ ### Write
85
+
86
+ Write tools are hidden while the diagram is read-only. Each call is checked against the
87
+ diagram first (unknown ids, taken ids, shapes the family lacks), applies as one undo step and
88
+ returns what it created or changed. All but `load_diagram_mermaid` and undo / redo refuse
89
+ text-only families.
90
+
91
+ | Tool | Use it to |
92
+ | --- | --- |
93
+ | `load_diagram_mermaid` | Replace the whole diagram with Mermaid `source` (fenced or bare; must start with a header such as `flowchart LR`). Use for new diagrams, wholesale rewrites and text-only families. Returns family, editable flag, node and edge counts and diagnostics. Rewrites the user's formatting, so prefer the per-operation tools for small changes. |
94
+ | `add_diagram_node` | Add a node with `label` (required); optional `id` (default the family's next free id), `shape`, `data` (family node fields), `parentId` (group), `from` plus `edgeLabel` to connect from an existing node, and `x` / `y` together in canvas px. Returns the node and any edge created. |
95
+ | `remove_diagram_nodes` | Delete nodes (`ids`) and every edge touching them. A group id removes the group but keeps its contents. Returns removed node and edge ids. |
96
+ | `rename_diagram_node` | Change the label of a node or group (`id`, `label`). |
97
+ | `set_diagram_node_shape` | Change a flowchart or state node's `shape` to one of the names `get_diagram` lists (such as `rect`, `rounded`, `stadium`, `diam`, `cyl`, `circle`, `hex`, `doc`). |
98
+ | `set_diagram_node_style` | Replace a node's inline Mermaid `styles` with `property:value` strings, e.g. `["fill:#fde68a", "stroke:#b45309", "stroke-width:2px"]`; an empty list removes them. |
99
+ | `set_diagram_node_data` | Set node field values (`id`, `data`): a pie slice `value`, Gantt `start` / `end`, quadrant `x` / `y`, journey score, XY series values, C4 technology. Keys and types come from `fields.node`; `null` clears a field. |
100
+ | `connect_diagram_nodes` | Draw an edge from `source` to `target` (existing node ids) with an optional `label`. Returns the edge id. |
101
+ | `remove_diagram_edges` | Delete edges by `ids`; the nodes stay. |
102
+ | `set_diagram_edge_label` | Set an edge's `label` by edge `id`; `""` removes it. |
103
+ | `set_diagram_edge_data` | Set edge field values (`id`, `data`): sequence activation, C4 relation technology, architecture sides. Keys from `fields.edge`; `null` clears. |
104
+ | `reconnect_diagram_edge` | Move an edge to a new `source` and `target`, keeping label and style. The returned edge id may change; use it from then on. |
105
+ | `set_diagram_direction` | Set the flow `direction`: `TB` / `TD`, `BT`, `LR` or `RL`. Refused by families whose layout follows their data (pie, sequence, Gantt...). |
106
+ | `set_diagram_title` | Set the `title` shown above the diagram, or `null` to remove it. |
107
+ | `set_diagram_settings` | Set diagram-level fields (`data`): pie `showData`, Gantt `dateFormat` and `excludes`, quadrant axis labels, XY categories and axis range, sequence autonumbering. Keys from `fields.diagram`; `null` clears. |
108
+ | `group_diagram_nodes` | Put `nodeIds` into a new group with `label` (optional `id`, default the next `G<number>`): a flowchart subgraph, composite state, class namespace, or the family's own group kind. Refused by families without groups (ER, pie, mindmap, quadrant, XY, radar). |
109
+ | `ungroup_diagram_group` | Remove a group by `id`; its nodes move to the group's parent. |
110
+ | `move_diagram_nodes` | Place nodes or groups on the canvas: `moves` of `{ id, x, y }` (top-left, canvas px). Stored in the `%% @pixerate` comment only; Mermaid statements and other renderers are unaffected. |
111
+ | `undo_diagram` | Undo the last diagram edit; returns its label. |
112
+ | `redo_diagram` | Redo the last undone diagram edit. |
113
+
114
+ ## Pitfalls
115
+
116
+ - Ids are Mermaid ids, not labels. Always take them from `get_diagram` or from what a write
117
+ returned; a custom `id` must match `^[A-Za-z0-9_][\w.-]*$` and not be taken.
118
+ - `load_diagram_mermaid` takes exactly one diagram. Text with several fenced diagrams is
119
+ refused; pick one with `find_mermaid_diagrams`. Text without a Mermaid header is refused
120
+ and nothing changes.
121
+ - Shapes only apply to flowchart and state nodes; class and ER have none. A shape name not
122
+ in `get_diagram`'s `shapes` is refused.
123
+ - Data tools check keys and types against the family's fields before changing anything.
124
+ Read `fields` first rather than guessing keys.
125
+ - Moving one node of an auto-laid diagram can shift the others when the host does not pin
126
+ current positions; check with `render_diagram` after `move_diagram_nodes`, and prefer
127
+ letting the layout place nodes (omit `x` / `y`) unless the user asked for a position.
128
+ - Mermaid label text with quotes, brackets or `#` may need quoting in the source; the
129
+ per-operation tools quote flowchart labels when needed, so prefer them over hand-written
130
+ text when labels contain punctuation, and check `diagnostics` after a `load_diagram_mermaid`.
131
+ - `export_diagram_mermaid` with `withLayout: false` is for plain Mermaid readers; keep the
132
+ comment when the text will come back into a Pixerate editor.
133
+ - When the diagram is read-only, only the read tools are listed and `get_diagram` returns
134
+ the reason. Tell the user; do not try to edit around it.
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: pixerate-generation
3
+ description: How to generate images, video, audio or text through Pixerate's AI generation tools safely - discovering models and their request schemas with list_models, checking a request with plan_generation (aspect ratio, resolution, quality, count, duration, seed, references with roles such as start_frame, style_ref, character_ref or mask, edit and inpaint modes), estimating cost and time with estimate_generation, starting a paid generation with generate and an idempotency key so retries never bill twice, and reusing past generations from the history (list_generations, recreate_generation, vary_generation) with drift reports. Use when asked to generate, render, create or edit media with an AI model, text-to-image, image-to-video, inpainting, or when list_models or generate are available.
4
+ ---
5
+
6
+ # AI generation
7
+
8
+ The generation tools front a host's model catalogue. Each model is a capability record (id,
9
+ media kind `image` / `video` / `audio` / `text`, which request fields it supports and their
10
+ options or ranges, which reference roles it accepts). A request is a plain object (`prompt`,
11
+ `aspectRatio`, `resolution`, `quality`, `count`, `duration`, `seed`, `mode`, `references`,
12
+ `params`, …); the planner checks it against the model, adjusts unsupported values per a
13
+ `strategy`, and reports every change. `generate` costs money or quota and cannot be undone.
14
+ See `pixerate-agent-tools` for errors and namespacing.
15
+
16
+ - **Model ids** come only from `list_models`. Never guess one from a brand name.
17
+ - **References** are assets the host already knows: `{ id, role, url?, mediaType?,
18
+ contentHash? }`. Ids come from the host (an asset library, an upload, a mention in the
19
+ prompt), never invented. Roles: `start_frame`, `end_frame`, `style_ref`, `character_ref`,
20
+ `background_ref`, `mask`, `image_ref`, `video_ref`, `audio_ref`, plus any role a model
21
+ declares; each model lists the roles it accepts and their min/max counts.
22
+
23
+ ## Working method
24
+
25
+ 1. **Discover.** `list_models` (filter with `media`) and read each candidate's `requestSchema`:
26
+ supported fields, enum options, ranges, prompt limits, reference roles.
27
+ 2. **Plan.** Build the request from the user's intent and call `plan_generation`. Read every
28
+ `adjustments` entry (`field`, `from`, `to`, `kind`, `reason`) and every `errors` entry. If
29
+ an adjustment changes what the user asked for (a different aspect ratio, a dropped
30
+ reference, fewer outputs), choose another model or tell the user before going on.
31
+ 3. **Estimate.** When `estimate_generation` is offered, call it with the same arguments. Report
32
+ the cost and time to the user and get confirmation when it is significant, when the user has
33
+ not already agreed to spend, or for any batch, high count, long video or top quality tier.
34
+ 4. **Generate once.** Call `generate` with the same `model`, `request`, `strategy` and a fresh
35
+ `idempotencyKey`. Return what it returns (typically a job id inside `result`) to the user.
36
+ 5. **On a timeout or transport error,** retry with the identical arguments and the same key.
37
+ Only change the key when you intend a new, separate generation.
38
+
39
+ To redo or vary an earlier result ("make that one again", "same but wider", "another take"),
40
+ find it with `list_generations`, inspect it with `get_generation`, and build the request with
41
+ `recreate_generation` or `vary_generation`. They return `model` and `request` ready for
42
+ `generate`, plus `drift`: tell the user about every `warning` or `error` item (an edited
43
+ template, a model that changed, a missing reference) before spending. Then continue from step 3.
44
+
45
+ ## Best practices
46
+
47
+ - **Plan before you pay.** `plan_generation` and `estimate_generation` are free and read-only;
48
+ `generate` is not. Never call `generate` to discover what a model supports.
49
+ - **Pick the strategy deliberately.** `nearest` (default) snaps and clamps, ties up, and may
50
+ drop unsupported references; `downgrade` ties down (cheaper, smaller); `upgrade` never drops
51
+ references, so a lost reference becomes an error; `error` changes nothing and fails on any
52
+ mismatch. Use `error` or `upgrade` when exact settings or every reference matter (brand
53
+ work, a required start frame); use `nearest` for exploration.
54
+ - **Write prompts for the medium.** Subject, then setting, composition and framing, lighting,
55
+ style and lens or medium; for video add camera motion and action over time. Put exclusions
56
+ in `negativePrompt` only when the model supports it (its schema says so). Keep the prompt
57
+ within the model's limit as resolved, not as written (see Pitfalls).
58
+ - **Match the deliverable.** Choose `aspectRatio` and `resolution` for where the result will be
59
+ used (16:9 video, 9:16 stories, 1:1 thumbnails, 4:5 feeds) rather than cropping later.
60
+ - **Explore cheap, finish expensive.** Draft at a low `quality` or `resolution` and small
61
+ `count`, then re-run the chosen direction at full quality with the same `seed` (when the
62
+ model supports seeds) for a closer match.
63
+ - **Batch sensibly.** Prefer one request with `count: n` over n requests when the model
64
+ supports it. For genuinely different requests, give each its own key and estimate the total
65
+ first. Do not fan out dozens of paid calls without the user's go-ahead.
66
+ - **Pass references with the right role.** A start frame for image-to-video as `start_frame`,
67
+ a look to copy as `style_ref`, a person or product to keep consistent as `character_ref`.
68
+ Editing needs `mode: "edit"` and a model with editing; inpainting needs `mode: "inpaint"`
69
+ plus a `mask` reference.
70
+ - **Keep provenance.** Record the model id, the planned request and seed the tools returned,
71
+ so the user can reproduce or vary a result.
72
+
73
+ ## Tool reference
74
+
75
+ ### Read
76
+
77
+ | Tool | Use it to |
78
+ | --- | --- |
79
+ | `list_models` | List available models: `id`, `media`, optional `name`, `description`, `badges`, and the `requestSchema` (JSON Schema of the request fields, options, ranges and reference roles it accepts). Optional `media` filter: image, video, audio or text. Call first; the list can change while you work. |
80
+ | `plan_generation` | Check a request without generating. Takes `model`, `request`, optional `strategy` (nearest default, upgrade, downgrade, error) and `resolvedPrompt`. Returns `plan`: `ok`, the adjusted `request`, `adjustments` (snapped, clamped, truncated, dropped, defaulted, each with a reason) and `errors`. Fix every error before estimating or generating. |
81
+ | `list_generations` | Find past generations (newest first): id, model, kind (generate, recreate, variation), parent, time, templates, assets and a 160-character prompt preview. Filter by `model`, `template`, `text`, `kind` or `parentId`; page with `limit` (default 20, max 100) and `offset`. Returns `total` too. |
82
+ | `get_generation` | Read one record by `id`: raw and resolved prompt, the settings as the user set them, strategy, the seed used, assets, templates and parent. Use it to answer what was used, or before a recreate. |
83
+ | `recreate_generation` | Build (not run) the request that reproduces a record. `mode` `exact` (default) keeps the recorded prompt and settings; `latest` uses current templates and re-plans for the current model. Returns `ok`, `model`, `request`, `resolvedPrompt`, `drift` and any `planErrors`. Pass `model` and `request` to `generate` with a new key. |
84
+ | `vary_generation` | Build (not run) a variation: the same prompt, settings and assets with a new `seed` (random unless given, `null` for none), `values` for prompt variables, `settings` merged over the recorded ones, or a new `rawPrompt`. Same result shape as `recreate_generation`. |
85
+ | `estimate_generation` | Get the host's cost and/or time estimate for the planned request (same arguments as `plan_generation`). Returns `plan` and `estimate`; nothing is generated. Only present when the host provides estimates; when it is missing, say you cannot quote a cost. A request that fails planning returns an `isError` result with code `plan_failed`. |
86
+
87
+ ### Write
88
+
89
+ | Tool | Use it to |
90
+ | --- | --- |
91
+ | `generate` | Plan and start a generation (paid, irreversible). Takes `model`, `request`, optional `strategy` and `resolvedPrompt`, and a required `idempotencyKey` (1..200 chars, unique per intended generation). Returns `result` (the host's value, e.g. a job id), the `plan` actually sent and the key; a retry with the same key and arguments returns the first result with `deduplicated: true`. Planning errors return `plan_failed` and generate nothing. |
92
+
93
+ ## Pitfalls
94
+
95
+ - **Idempotency keys:** the same key with different arguments is rejected ("already used with
96
+ different arguments"); use a new key for a new generation. A failed call forgets its key, so
97
+ retrying a failure with the same key does generate. Never reuse a key to "regenerate" or to
98
+ get a variation: that returns the old result.
99
+ - **Templates:** when `request.prompt` contains template variables, pass the expanded text as
100
+ `resolvedPrompt`. Limits count the resolved text; when it is over the limit the plan errors
101
+ under every strategy and the prompt is not truncated. Shorten the resolved prompt yourself.
102
+ - **Read adjustments, not just `ok`.** `ok: true` under `nearest` can still mean a reference was
103
+ dropped or the count reduced. Compare the adjusted request with what the user asked for.
104
+ - **Unknown model:** a model id not in the current catalogue fails validation; call
105
+ `list_models` again (the catalogue may have changed) instead of retrying the same id.
106
+ - `generate` only starts the job; the result may be a job id rather than media. Do not call it
107
+ again to "check" progress; that is a new paid request unless the key and arguments match.
108
+ - `idempotencyKey` belongs only on `generate`; `plan_generation` and `estimate_generation`
109
+ reject it as an unknown argument.
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: pixerate-image-editor
3
+ description: How to colour-correct and retouch a photo in the Pixerate image editor through its agent tools - base adjustments (exposure, contrast, white balance temperature and tint, saturation, blur), non-destructive adjustment layers (curves, levels, hue/saturation, vibrance, color balance, black and white, photo filter, invert, posterize, threshold) with blend modes and opacity, selections (rectangle, ellipse, magic wand, color range, grow, shrink, feather, refine edge) and layer masks, crop, rotate and flip, undo, reading the histogram for clipping, and rendering a PNG preview to check the result. Use when asked to edit, grade, correct, brighten, warm up, desaturate, crop, straighten or mask an image, or when get_adjustments, set_adjustments, add_adjustment_layer, select_by_color or render_preview are available.
4
+ ---
5
+
6
+ # Image editor
7
+
8
+ The image editor holds one source image plus a stack of edits that never touch the source
9
+ pixels: base adjustments (one value per control id), adjustment layers applied bottom to top
10
+ on top of the base, an optional selection, crop/rotate/flip and annotations. Rendering order:
11
+ base adjustments, then layers bottom to top (each through its mask, opacity and blend mode),
12
+ then blur. See `pixerate-agent-tools` for errors, namespacing and command batching.
13
+
14
+ - **Control ids** for base adjustments: `brightness`, `contrast`, `exposure`, `temperature`,
15
+ `tint`, `saturation` (all -100..100, default 0), `blur` (0..30 px) and `opacity` (0..1).
16
+ `list_controls` is the source of truth for ranges, steps and defaults.
17
+ - **Layer ids** (e.g. `adj_1`) come from `add_adjustment_layer` / `apply_selection_as_mask`
18
+ and `get_adjustments`. Layer parameters are addressed as `layers.<layerId>.<controlId>`,
19
+ where nested params use dots: `layers.adj_2.master.gamma` (levels),
20
+ `layers.adj_3.ranges.0.saturation` (hue/saturation reds), `layers.adj_4.shadows.2`
21
+ (color balance yellow-blue), `layers.adj_1.opacity`.
22
+ - **Coordinates** for selections are natural pixels of the source image (before crop, rotate
23
+ or flip). Read `get_selection` bounds or the image size, never screen pixels.
24
+
25
+ ## Working method
26
+
27
+ 1. **Read.** `get_adjustments` for the current values, process version and layers;
28
+ `get_image_info` for the image size, crop and rotation; `list_controls` once for control
29
+ ids, ranges, layer kinds and blend modes; `render_preview` (default 512 px) to see the
30
+ image, then `get_histogram` to judge exposure and clipping in numbers.
31
+ 2. **Plan the order of corrections** (see Best practices): straighten and crop first (so
32
+ later judgements are on the final frame), then global tone and white balance,
33
+ then contrast and tone curves, then colour, then local fixes through masks, then creative
34
+ looks.
35
+ 3. **Write in few steps.** Put every base change of one correction into one `set_adjustments`
36
+ call (one undo step) with a `label`. Create layers with their `params` in the same
37
+ `add_adjustment_layer` call rather than adding a neutral layer and then setting it.
38
+ 4. **Local edits:** select (`select_region`, `select_by_color`), refine (`modify_selection`,
39
+ `refine_selection`), check with `get_selection` (area, percent, bounds), then
40
+ `apply_selection_as_mask` with a `kind` to create the masked layer in one step.
41
+ 5. **Verify.** `render_preview` after each group of corrections, not after each slider, then
42
+ `get_histogram` (it reads the last render) for clipping. Compare against the previous
43
+ preview; read the `applied` and `clamped` lists that writes return. `undo_image` takes back a
44
+ step that made things worse.
45
+
46
+ ## Best practices
47
+
48
+ - **Non-destructive first.** Prefer an adjustment layer over pushing a base slider to its
49
+ limit: layers can be masked, faded with `opacity`, blended and stacked. Use base sliders for
50
+ global exposure and white balance, layers for everything you may want to tune later.
51
+ - **Order of corrections** (as in a raw / Photoshop workflow): exposure and white balance
52
+ (`exposure`, `temperature`, `tint`) → black and white points and contrast (a `levels` layer,
53
+ then a gentle S-curve `curves` layer) → colour (`vibrance` before `saturation`,
54
+ `hueSaturation` per range, `colorBalance`) → local adjustments through masks → creative looks
55
+ (`photoFilter`, `blackWhite`, `posterize`). Correct before you stylise.
56
+ - **Avoid clipping.** Set levels black and white points (`master.inBlack`, `master.inWhite`)
57
+ just inside where the image data starts (the histogram's `p1` / `p99`), not past it; large
58
+ `exposure` or `contrast` values blow highlights and crush shadows in the output. More than
59
+ about 0.5% of pixels in `clipping.highlightsPercent` or `shadowsPercent` on a normal photo
60
+ means detail is lost; check bright skies, skin and deep shadows in `render_preview` too.
61
+ - **Straighten, then crop.** Level horizons with `set_rotation` (small angles such as -2.5);
62
+ any angle that is not a quarter turn leaves transparent corners, so crop inside them with
63
+ `set_crop` afterwards. Keep a standard aspect ratio (3:2, 4:3, 16:9, 1:1, 4:5) unless asked
64
+ otherwise, and do not crop away the subject's space to look or move into.
65
+ - **Small moves.** Real corrections are usually within ±10..30 on these scales. Prefer
66
+ `vibrance` over `saturation` for portraits (it protects already-saturated colours and skin).
67
+ - **Contrast through curves.** A curves S-curve keeps endpoints fixed and avoids the flat
68
+ greys that a big `contrast` value with low `exposure` produces. Curve points are levels
69
+ 0..255 (`{ input, output }`); keep `(0,0)` and `(255,255)` and move quarter-tones by 10..25.
70
+ - **Neutral greys.** Use `temperature` / `tint` (or `colorBalance` midtones) so known-neutral
71
+ areas (white walls, grey roads, clouds) have no cast; then add warmth deliberately if wanted.
72
+ - **Masks: select, refine, then mask.** Clean the selection before masking: `smooth` for
73
+ jagged wand edges, `refine_selection` for hair and soft edges, feather in proportion to the
74
+ image (a few px for hard objects, tens of px for sky or vignette transitions). Use the mask's
75
+ own `feather` and `density` on `apply_selection_as_mask` so softening stays adjustable.
76
+ - **Blend modes for tone-only or colour-only changes:** `luminosity` applies a curves or
77
+ levels layer without shifting hue or saturation; `color` applies a tint without changing
78
+ brightness; `soft-light` / `overlay` for gentle contrast.
79
+ - **Name layers** (`name`) by intent ("Sky darken", "Warm skin"), so the stack stays readable.
80
+
81
+ ## Tool reference
82
+
83
+ ### Read
84
+
85
+ | Tool | Use it to |
86
+ | --- | --- |
87
+ | `get_adjustments` | Read the current state: `values` by control id, `process` version (1 or 2), and `layers` bottom to top with id, kind, params, opacity, blend, enabled and mask. Call first, and to find layer ids. |
88
+ | `list_controls` | Get every base control (id, label, section, min, max, step, default, `requiresProcess`), each layer kind's settable controls (plus `opacity`), the blend mode ids and the `layers.<layerId>.<controlId>` path format. Call once per session before writing. |
89
+ | `get_selection` | Read the active selection: `empty`, `bounds` (natural pixels), `area` in pixels, `percent` of the image and a description. Check it after every select or modify step and before masking: a wand that covered 90% of the image is the wrong selection. |
90
+ | `get_image_info` | Read the geometry: source `image` size, `crop` box (source pixels, or null), `rotation` degrees, `flipH` / `flipV`, the `output` size after crop and rotation, the layer count and `canUndo` / `canRedo`. Call before cropping or selecting so coordinates are right. |
91
+ | `get_histogram` | Judge exposure numerically: per channel and luminance `mean`, `p1` and `p99` (0..255), and `clipping` percent at pure black and white per channel. Reads the last render, so call `render_preview` first. `bins` (16, 32, 64 or 256) adds the counts. Cheaper than another image for checking a tonal change. |
92
+ | `render_preview` | See the edited image (crop, adjustments, layers, annotations) as a PNG. `maxSide` 16..2048 px, default 512. Images cost tokens: render after a group of edits, use 512 for overall look and 1024+ to judge clipping, edges and masks. Fails in environments without rendering. |
93
+
94
+ ### Write
95
+
96
+ | Tool | Use it to |
97
+ | --- | --- |
98
+ | `set_adjustments` | Set base controls and existing layer parameters in one undo step: `values` is a map of control id or `layers.<layerId>.<controlId>` path to number; `label` is echoed. Values are clamped to range; returns `applied` and `clamped` (and a note when `tint` is set on a process 1 edit). Unknown ids fail and change nothing. Cannot set curves points, booleans or colours. |
99
+ | `add_adjustment_layer` | Add a layer on top of the stack: `kind` (curves, levels, hueSaturation, vibrance, colorBalance, blackWhite, photoFilter, invert, posterize, threshold), optional `params` merged with neutral defaults, `opacity` 0..1 (default 1), `blend` (default normal), `name`. Returns the layer (with its new id) and its stack index. The only tool that sets curves points, `colorize`, `preserveLuminosity`, a black and white `tint` or a photo filter `color`. |
100
+ | `select_region` | Select by `shape`: `rect` or `ellipse` (with `x`, `y`, `width`, `height` in natural pixels), `all`, `none` or `invert`. `mode` replace (default), add, subtract or intersect; `feather` px (default 0). Returns the selection summary. |
101
+ | `select_by_color` | Magic wand from a seed (`x`, `y`, `tolerance` 0..255 default 32, `contiguous` default true) or Color Range for every similar pixel (`color` "#rrggbb", `fuzziness` 0..200 default 40). `sampleMerged: true` samples the adjusted image instead of the source. `mode` as above. Use it for skies, backdrops and flat-coloured objects. |
102
+ | `modify_selection` | Grow, shrink, feather, border or smooth the selection (`op`) by `radius` px (0..500). Use shrink then feather to keep an adjustment from bleeding over an edge; smooth to remove wand speckle. Fails when nothing is selected. |
103
+ | `refine_selection` | Refine Edge: snap the selection edge to image edges within `radius` px (0..64, default 8), with `smartRadius`, `smooth` 0..100, `feather` px, `contrast` 0..100 and `shiftEdge` -100..100 %. Use on hair, fur, foliage or after loading a coarse AI mask. |
104
+ | `update_adjustment_layer` | Change a layer's `enabled` (false hides it without deleting), `blend`, `opacity` (0..1) or `name` in one undo step. Returns the layer. Its parameters change with `set_adjustments`. Toggle `enabled` to compare a layer's effect before and after. |
105
+ | `move_adjustment_layer` | Move a layer to index `to` (0 = bottom, applied first; past the top means top). Order matters: a curves layer above a hue/saturation layer works on its output. Fails when the layer is already there. Returns the ids bottom to top. |
106
+ | `remove_adjustment_layer` | Delete a layer and its mask. Prefer hiding it with `update_adjustment_layer` when the user may want it back. Returns the remaining ids. |
107
+ | `set_crop` | Crop to `x`, `y`, `width`, `height` in source pixels of the un-rotated image (see `get_image_info`). Non-destructive; refused if the box leaves the image. For an aspect ratio, compute the largest box of that ratio inside the image and centre it on the subject. Returns the geometry. |
108
+ | `reset_crop` | Remove the crop and show the whole image again. |
109
+ | `set_rotation` | Set the absolute rotation in degrees clockwise (-360..360). Quarter turns keep every pixel; small angles straighten a horizon but add transparent corners to crop away. Returns the geometry. |
110
+ | `flip_image` | Mirror the image `horizontal` (left-right) or `vertical`. Avoid flipping images with text, logos or recognisable places. |
111
+ | `undo_image` | Undo the last edit (one tool call is one step). Returns `canUndo` / `canRedo`. |
112
+ | `redo_image` | Redo the edit you just undid. |
113
+ | `apply_selection_as_mask` | Mask a layer with the current selection: pass `layerId` to mask an existing layer, or `kind` (plus optional `params`) to create a new masked layer in one step. `density` 0..1 and `feather` px soften the mask non-destructively. Returns `layerId`, kind, mask info and the selection summary. |
114
+
115
+ ## Pitfalls
116
+
117
+ - A layer's `kind` cannot change; to switch kinds add a new layer and remove the old one.
118
+ Curves points, `colorize` and colours are only set when the layer is added, so get them
119
+ right in `add_adjustment_layer` (or replace the layer).
120
+ - `get_histogram` describes the last render, not the current state: render after edits, then
121
+ read it.
122
+ - Crop coordinates are always in the un-rotated source; after `set_rotation` the output size
123
+ swaps for quarter turns, but the crop box does not.
124
+ - `set_adjustments` clamps silently: always read `clamped`. If a value you needed was clamped,
125
+ the correction needs a layer (e.g. levels or curves), not a bigger number.
126
+ - `tint` has no effect on process 1 edits (older saved documents); the result carries a note.
127
+ Do not keep raising it; correct the green-magenta cast with a `colorBalance` layer instead.
128
+ - Base `opacity` fades the whole image, not an adjustment. Base `blur` blurs the whole output
129
+ after all layers; it is not a local softening tool.
130
+ - `invert` and `threshold` are destructive-looking creative effects; never use them for a
131
+ correction the user did not ask for. Posterize `levels` below ~8 bands visibly.
132
+ - Selection coordinates ignore crop and rotation: they are source-image pixels. A rectangle in
133
+ the cropped preview's coordinates lands in the wrong place on a cropped image.
134
+ - `select_by_color` without `x`/`y` or `color` fails. Large `tolerance` / `fuzziness` floods the
135
+ selection: start low (wand 20..40, range 30..60), check `percent`, and add with `mode: add`.
136
+ - `modify_selection`, `refine_selection` and `apply_selection_as_mask` fail with "Nothing is
137
+ selected." when the selection is empty; select first.
138
+ - Opacity values are 0..1, not percent. Curves and levels points are 0..255 levels; levels
139
+ `gamma` is 0.1..9.99 (1 = neutral); hue is degrees -180..180.