@pinepaper.studio/mcp-server 1.6.15 → 1.6.17
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.
- package/README.de.md +1 -1
- package/README.es.md +1 -1
- package/README.fr.md +1 -1
- package/README.hi.md +1 -1
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +110 -4
- package/README.pt-BR.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/build-info.json +2 -2
- package/dist/ontology/upstream-vocabulary.d.ts +2 -2
- package/dist/ontology/upstream-vocabulary.js +2 -2
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +164 -19
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/engine-methods.d.ts.map +1 -1
- package/dist/tools/engine-methods.js +4 -0
- package/dist/tools/engine-methods.js.map +1 -1
- package/dist/tools/engine-surface.d.ts +1 -1
- package/dist/tools/engine-surface.d.ts.map +1 -1
- package/dist/tools/engine-surface.js +30 -9
- package/dist/tools/engine-surface.js.map +1 -1
- package/dist/tools/handlers/beats.d.ts +64 -0
- package/dist/tools/handlers/beats.d.ts.map +1 -0
- package/dist/tools/handlers/beats.js +83 -0
- package/dist/tools/handlers/beats.js.map +1 -0
- package/dist/tools/handlers/camera.d.ts.map +1 -1
- package/dist/tools/handlers/camera.js +11 -0
- package/dist/tools/handlers/camera.js.map +1 -1
- package/dist/tools/handlers/generate.d.ts +324 -0
- package/dist/tools/handlers/generate.d.ts.map +1 -0
- package/dist/tools/handlers/generate.js +264 -0
- package/dist/tools/handlers/generate.js.map +1 -0
- package/dist/tools/handlers.d.ts.map +1 -1
- package/dist/tools/handlers.js +79 -9
- package/dist/tools/handlers.js.map +1 -1
- package/dist/tools/minimal-descriptions.d.ts.map +1 -1
- package/dist/tools/minimal-descriptions.js +5 -0
- package/dist/tools/minimal-descriptions.js.map +1 -1
- package/dist/tools/shape-params.d.ts +2 -2
- package/dist/tools/shape-params.js +2 -2
- package/dist/tools/stick-vocabulary.d.ts +1 -1
- package/dist/tools/stick-vocabulary.js +1 -1
- package/dist/tools/toolkits.d.ts.map +1 -1
- package/dist/tools/toolkits.js +5 -0
- package/dist/tools/toolkits.js.map +1 -1
- package/dist/types/code-generator.d.ts +38 -0
- package/dist/types/code-generator.d.ts.map +1 -1
- package/dist/types/code-generator.js +552 -44
- package/dist/types/code-generator.js.map +1 -1
- package/dist/types/schemas.d.ts +614 -82
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/types/schemas.js +53 -21
- package/dist/types/schemas.js.map +1 -1
- package/dist/utils/a11y.d.ts +2 -0
- package/dist/utils/a11y.d.ts.map +1 -1
- package/dist/utils/a11y.js +1 -1
- package/dist/utils/a11y.js.map +1 -1
- package/dist/utils/beats.d.ts +58 -0
- package/dist/utils/beats.d.ts.map +1 -0
- package/dist/utils/beats.js +110 -0
- package/dist/utils/beats.js.map +1 -0
- package/dist/utils/svg-size.d.ts +22 -0
- package/dist/utils/svg-size.d.ts.map +1 -0
- package/dist/utils/svg-size.js +43 -0
- package/dist/utils/svg-size.js.map +1 -0
- package/dist/vendor/design/design-style.js +1 -1
- package/manifest.json +21 -1
- package/package.json +1 -1
package/README.de.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
Der PinePaper MCP-Server lässt KI-Assistenten über das Model Context Protocol Grafiken in [PinePaper Studio](https://pinepaper.studio) erstellen und animieren. Funktioniert mit jeder KI, die MCP-Tool-Aufrufe unterstützt (Claude, GPT, Gemini, lokale Modelle usw.).
|
|
21
21
|
|
|
22
|
-
Der Server bietet **
|
|
22
|
+
Der Server bietet **159 Tools**: Zeichnen, Animation, Diagramme, Karten, Typografie, Physik, Bildbearbeitung, Datenvisualisierung und Export:
|
|
23
23
|
|
|
24
24
|
- Text, Formen, Geometrie und komplexe Grafiken erstellen
|
|
25
25
|
- Mit deklarativen **Relationen** animieren statt mit Keyframes
|
package/README.es.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
El servidor MCP de PinePaper permite a los asistentes de IA crear y animar gráficos en [PinePaper Studio](https://pinepaper.studio) a través del Model Context Protocol. Funciona con cualquier IA que soporte llamadas a herramientas MCP (Claude, GPT, Gemini, modelos locales, etc.).
|
|
21
21
|
|
|
22
|
-
Expone **
|
|
22
|
+
Expone **159 herramientas**: dibujo, animación, diagramas, mapas, tipografía, física, edición de imágenes, visualización de datos y exportación:
|
|
23
23
|
|
|
24
24
|
- Crear texto, formas, geometría y gráficos complejos
|
|
25
25
|
- Animar con **relaciones** declarativas en lugar de fotogramas clave
|
package/README.fr.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
Le serveur MCP PinePaper permet aux assistants IA de créer et d'animer des graphiques dans [PinePaper Studio](https://pinepaper.studio) via le Model Context Protocol. Compatible avec toute IA gérant les appels d'outils MCP (Claude, GPT, Gemini, modèles locaux, etc.).
|
|
21
21
|
|
|
22
|
-
Il expose **
|
|
22
|
+
Il expose **159 outils** : dessin, animation, diagrammes, cartes, typographie, physique, retouche d'image, visualisation de données et export :
|
|
23
23
|
|
|
24
24
|
- Créer du texte, des formes, de la géométrie et des graphiques complexes
|
|
25
25
|
- Animer avec des **relations** déclaratives plutôt que des images clés
|
package/README.hi.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
PinePaper MCP सर्वर AI असिस्टेंट्स को Model Context Protocol के ज़रिए [PinePaper Studio](https://pinepaper.studio) में ग्राफ़िक्स बनाने और एनिमेट करने देता है। MCP टूल कॉलिंग वाले किसी भी AI (Claude, GPT, Gemini, लोकल मॉडल आदि) के साथ काम करता है।
|
|
21
21
|
|
|
22
|
-
सर्वर **
|
|
22
|
+
सर्वर **159 टूल** देता है — ड्रॉइंग, एनिमेशन, डायग्राम, नक्शे, टाइपोग्राफ़ी, फिज़िक्स, इमेज एडिटिंग, डेटा विज़ुअलाइज़ेशन और एक्सपोर्ट:
|
|
23
23
|
|
|
24
24
|
- टेक्स्ट, आकृतियाँ, ज्यामिति और जटिल ग्राफ़िक्स बनाना
|
|
25
25
|
- कीफ़्रेम की जगह व्यवहार बताने वाले **रिलेशन** से एनिमेशन
|
package/README.ja.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
PinePaper MCP サーバーは、MCP 経由で AI アシスタントが [PinePaper Studio](https://pinepaper.studio) 上にグラフィックを作成・アニメーションさせるためのサーバーです。MCP ツールコールに対応した AI(Claude、GPT、Gemini、ローカルモデルなど)で動作します。
|
|
21
21
|
|
|
22
|
-
**
|
|
22
|
+
**159 個のツール**を提供 — 描画・アニメーション・図・地図・タイポグラフィ・物理・画像編集・データ可視化・エクスポート:
|
|
23
23
|
|
|
24
24
|
- テキスト、図形、ジオメトリ、複雑なグラフィックの作成
|
|
25
25
|
- キーフレームではなく、ふるまいを宣言する**リレーション**でアニメーション
|
package/README.ko.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
PinePaper MCP 서버는 AI 어시스턴트가 MCP를 통해 [PinePaper Studio](https://pinepaper.studio)에서 그래픽을 만들고 애니메이션하게 해줍니다. MCP 툴 콜을 지원하는 모든 AI(Claude, GPT, Gemini, 로컬 모델 등)와 호환됩니다.
|
|
21
21
|
|
|
22
|
-
**
|
|
22
|
+
**159개의 툴** 제공 — 드로잉, 애니메이션, 다이어그램, 지도, 타이포그래피, 물리, 이미지 편집, 데이터 시각화, 내보내기:
|
|
23
23
|
|
|
24
24
|
- 텍스트·도형·기하·복잡한 그래픽 생성
|
|
25
25
|
- 키프레임 대신 행동을 선언하는 **릴레이션**으로 애니메이션
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
PinePaper MCP Server enables AI assistants to create and animate graphics in [PinePaper Studio](https://pinepaper.studio) via the Model Context Protocol (MCP). Works with any AI that supports MCP tool calling (Claude, GPT, Gemini, local models, etc.).
|
|
32
32
|
|
|
33
|
-
The server exposes **
|
|
33
|
+
The server exposes **159 tools** across drawing, animation, diagrams, maps, typography, physics, image editing, data visualization, and export. Using natural language, you can:
|
|
34
34
|
|
|
35
35
|
- Create geometric shapes, text collages, diagrams, and data charts
|
|
36
36
|
- Apply 37+ character-level text effects and 28+ vertex deformation presets
|
|
@@ -41,7 +41,7 @@ The server exposes **154 tools** across drawing, animation, diagrams, maps, typo
|
|
|
41
41
|
|
|
42
42
|
## Running it: local or hosted
|
|
43
43
|
|
|
44
|
-
**Local is free and complete.** Every one of the
|
|
44
|
+
**Local is free and complete.** Every one of the 159 tools works when you run
|
|
45
45
|
this server yourself. There is no reduced tier and nothing held back.
|
|
46
46
|
|
|
47
47
|
What it needs:
|
|
@@ -246,6 +246,105 @@ If you do not want an agent executing anything, `code` mode is a first-class pat
|
|
|
246
246
|
- Puppeteer mode launches Chrome with `--no-sandbox` and `--disable-setuid-sandbox`. That is routine for headless automation and it does weaken Chrome's own process sandbox. If that matters where you are running it, use `code` mode or put the server in a container.
|
|
247
247
|
- Puppeteer itself is an **optional** peer dependency, kept out of the default tree precisely because a headless browser plus an install script is what scanners flag hardest. Install it only if you want the executing mode.
|
|
248
248
|
|
|
249
|
+
## What's new in 1.6.17
|
|
250
|
+
|
|
251
|
+
### New: tell an agent "at 4 s, make it orange"
|
|
252
|
+
|
|
253
|
+
`pinepaper_modify_item` takes `atTime`: the change is written as a keyframe at
|
|
254
|
+
that moment, the same as dragging with auto-key on, eased from the previous
|
|
255
|
+
value and without disturbing the rest of the animation.
|
|
256
|
+
`pinepaper_query_mutations` shows a property's values over time.
|
|
257
|
+
|
|
258
|
+
### New: cuts on the beat
|
|
259
|
+
|
|
260
|
+
`pinepaper_beat_cuts` analyses a music track, fits a beat grid and returns cut
|
|
261
|
+
points on every beat, every bar or every N beats — and can split a clip at each.
|
|
262
|
+
When the tempo is uncertain it says so and lists the likely alternatives;
|
|
263
|
+
`bpm` or `bpmHint` settles it.
|
|
264
|
+
|
|
265
|
+
### New: exact frame counts, and larger canvases
|
|
266
|
+
|
|
267
|
+
- `pinepaper_agent_export` takes `frames` for an exact frame count (a duration
|
|
268
|
+
rounds up), for segments that must line up.
|
|
269
|
+
- Canvases up to 16384 px per side, for digital out-of-home and projection;
|
|
270
|
+
above 8192 the result notes that Safari and iOS may not manage it.
|
|
271
|
+
- `pinepaper_import_image` takes `maxEdge` (or `'native'`) and `nativeSize`, and
|
|
272
|
+
says when the studio stored an image smaller than its source.
|
|
273
|
+
- `pinepaper_media` `upload_video` takes `fit` (`contain`, `cover`, `none`), and
|
|
274
|
+
`scale` is documented as relative to it.
|
|
275
|
+
|
|
276
|
+
### Changed: exports say more about what they produced
|
|
277
|
+
|
|
278
|
+
- When an MP4 cannot be made at the requested size, the file is named by what it
|
|
279
|
+
is (WebM) and a warning says why.
|
|
280
|
+
- A video whose animation did not play, or whose encoder froze, is flagged.
|
|
281
|
+
- Asking for ProRes or HAP explains the route that works (a PNG sequence).
|
|
282
|
+
- Frame captures, region stills and flash checks wait for video on screen, and
|
|
283
|
+
report whether they could.
|
|
284
|
+
- The engine's structured warnings reach the caller whole.
|
|
285
|
+
|
|
286
|
+
### Fixed
|
|
287
|
+
|
|
288
|
+
- `pinepaper_accessibility_check` judged text only at the current playhead, so
|
|
289
|
+
timed captions could pass unchecked; it now samples the timeline, and says
|
|
290
|
+
when no text was visible rather than passing.
|
|
291
|
+
- `pinepaper_agent_export` accepts `fps` and `scale` for APNG.
|
|
292
|
+
|
|
293
|
+
## What's new in 1.6.16
|
|
294
|
+
|
|
295
|
+
### New: video editing on the timeline
|
|
296
|
+
|
|
297
|
+
`pinepaper_media` gains `split` (cut a clip in two at a time),
|
|
298
|
+
`add_transition` (a crossfade or a dip between two clips that meet), and
|
|
299
|
+
`set_clip` with `timeOffset` to move a clip, not only trim it. Uploads take
|
|
300
|
+
`atPlayhead: true` to start at the current playback time. A studio that cannot
|
|
301
|
+
do one of these says so rather than reporting success.
|
|
302
|
+
|
|
303
|
+
### New: AI image generation (beta)
|
|
304
|
+
|
|
305
|
+
`pinepaper_generate` creates images with AI models in the PinePaper cloud and
|
|
306
|
+
can place the first one on the canvas; `pinepaper_generate_estimate` prices a
|
|
307
|
+
request and lists the models, free. It is charged per image, needs a service
|
|
308
|
+
account key (`PINEPAPER_API_KEY`), and is enabled per organisation during the
|
|
309
|
+
beta — without it the tools say so, and nothing is charged.
|
|
310
|
+
|
|
311
|
+
Words are never drawn by the model: pass them as `input.text` (headline,
|
|
312
|
+
subhead, caption, call to action, label) and they are added as real, editable
|
|
313
|
+
PinePaper text over the image, laid out inside the title-safe area and given a
|
|
314
|
+
dark backing only where the image behind them is too bright to read.
|
|
315
|
+
|
|
316
|
+
### New: add to an animation instead of replacing it
|
|
317
|
+
|
|
318
|
+
`pinepaper_keyframe_animate` takes `append: true` to add keys to an item's
|
|
319
|
+
existing animation — a button press after an entrance. Without it, a second
|
|
320
|
+
call replaces the animation, and the result now says when that happened.
|
|
321
|
+
|
|
322
|
+
### New: byte-identical exports
|
|
323
|
+
|
|
324
|
+
`pinepaper_agent_export` takes `deterministic: true` for MP4 and WebM: the same
|
|
325
|
+
scene gives the same file, so exports can be checksummed or cached by hash. If
|
|
326
|
+
a run could not be pinned, the result says not to rely on the hash.
|
|
327
|
+
|
|
328
|
+
### Fixed
|
|
329
|
+
|
|
330
|
+
- `pinepaper_import_asset` with a `url` failed on every call after fetching the
|
|
331
|
+
file successfully.
|
|
332
|
+
- `pinepaper_sound` `render_soundtrack` timed out on longer soundtracks; it now
|
|
333
|
+
has the same time budget as other exports.
|
|
334
|
+
- `pinepaper_audio_beats` answered success with no result for larger audio, and
|
|
335
|
+
could not read a local file path. Both work now.
|
|
336
|
+
- `pinepaper_camera_animate` without keyframes failed with a raw JSON error; it
|
|
337
|
+
now says what `keyframes` needs.
|
|
338
|
+
- `pinepaper_precomp`: `create` returned an internal id that no tool accepted,
|
|
339
|
+
and `add` / `remove` could not work at all. All three now round-trip the
|
|
340
|
+
precomp's item id, and a failed `remove` is reported.
|
|
341
|
+
- `pinepaper_media` `set_time_remap`, `speed_ramp`, `match_cut` and the track
|
|
342
|
+
matte actions accept the media id that upload returns, as documented.
|
|
343
|
+
- `modify_item` `content` on text whose content is keyframed now warns that the
|
|
344
|
+
keyframes override it.
|
|
345
|
+
- Exporting a landscape canvas for a portrait platform (TikTok, Stories) — or
|
|
346
|
+
the reverse — is a fidelity warning with the fix, not only a note.
|
|
347
|
+
|
|
249
348
|
## What's new in 1.6.15
|
|
250
349
|
|
|
251
350
|
### New: the PinePaper mark
|
|
@@ -1171,7 +1270,7 @@ Fourteen new tools (121 → 135) and new actions across the surface — the rele
|
|
|
1171
1270
|
|
|
1172
1271
|
## Toolkits & Token Budget
|
|
1173
1272
|
|
|
1174
|
-
|
|
1273
|
+
159 tools is a lot of context. The server ships a **toolkit** system that serves only the tools a given client needs, plus a **verbosity** system that controls how long each tool description is.
|
|
1175
1274
|
|
|
1176
1275
|
**Toolkit profiles** (`PINEPAPER_TOOLKIT`):
|
|
1177
1276
|
|
|
@@ -1376,7 +1475,7 @@ Generate instruction/code pairs for LLM fine-tuning:
|
|
|
1376
1475
|
|
|
1377
1476
|
## Tools Reference
|
|
1378
1477
|
|
|
1379
|
-
All
|
|
1478
|
+
All 159 tools, grouped by the tag used for toolkit filtering.
|
|
1380
1479
|
|
|
1381
1480
|
### Canvas (`canvas`)
|
|
1382
1481
|
| Tool | Description |
|
|
@@ -1477,6 +1576,9 @@ All 154 tools, grouped by the tag used for toolkit filtering.
|
|
|
1477
1576
|
|------|-------------|
|
|
1478
1577
|
| `pinepaper_execute_generator` | Run a background generator |
|
|
1479
1578
|
| `pinepaper_list_generators` | List available generators |
|
|
1579
|
+
| `pinepaper_generate` | AI image generation in the PinePaper cloud (charged; beta, per organisation) |
|
|
1580
|
+
| `pinepaper_generate_estimate` | Free price check, and the model list |
|
|
1581
|
+
| `pinepaper_generate_status` | Collect a generation that outlived its timeout |
|
|
1480
1582
|
| `pinepaper_apply_effect` | Apply sparkle, blast, and other effects |
|
|
1481
1583
|
| `pinepaper_text_effect` | 37 character-level text animations; replaces the text with one keyframed item per character |
|
|
1482
1584
|
| `pinepaper_add_filter` | Add an image filter |
|
|
@@ -1595,6 +1697,8 @@ All 154 tools, grouped by the tag used for toolkit filtering.
|
|
|
1595
1697
|
| `pinepaper_analyze_design` | Analyze design quality |
|
|
1596
1698
|
| `pinepaper_validate_design` | Validate against design rules |
|
|
1597
1699
|
| `pinepaper_validate` | General validation |
|
|
1700
|
+
| `pinepaper_beat_cuts` | Cut points on the music's beats or bars; split a clip at each |
|
|
1701
|
+
| `pinepaper_query_mutations` | A property's keyframe series over time |
|
|
1598
1702
|
| `pinepaper_accessibility_check` | Text contrast and flashing (WCAG), as a heuristic screen |
|
|
1599
1703
|
| `pinepaper_validate_scene` | Validate scene integrity |
|
|
1600
1704
|
| `pinepaper_instantiate_ontology` | Compile a pp: design graph into a scene |
|
|
@@ -1871,6 +1975,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
|
|
|
1871
1975
|
|----------|-------------|---------|
|
|
1872
1976
|
| `PINEPAPER_STUDIO_URL` | PinePaper Studio URL to connect to (`/editor` is appended automatically) | `https://pinepaper.studio` |
|
|
1873
1977
|
| `PINEPAPER_HEADLESS` | Run the browser headless (set `false` to watch it work) | `true` |
|
|
1978
|
+
| `PINEPAPER_API_KEY` | Service-account key (`pp_sa_…`) for the cloud-backed tools (`pinepaper_generate`) | — |
|
|
1979
|
+
| `PINEPAPER_CLOUD_URL` | The PinePaper cloud those tools call | `https://cloud.pinepaper.studio` |
|
|
1874
1980
|
| `PINEPAPER_EXECUTION_MODE` | `puppeteer` (execute in a real browser) or `code` (return generated code only) | `puppeteer` |
|
|
1875
1981
|
| `PINEPAPER_EXPORT_DIR` | Directory for exported files | `<tmpdir>/pinepaper-exports` |
|
|
1876
1982
|
| `PINEPAPER_LOCALE` | Language locale code | `en` |
|
package/README.pt-BR.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
O servidor MCP do PinePaper permite que assistentes de IA criem e animem gráficos no [PinePaper Studio](https://pinepaper.studio) via Model Context Protocol. Funciona com qualquer IA que suporte chamadas de ferramenta MCP (Claude, GPT, Gemini, modelos locais etc.).
|
|
21
21
|
|
|
22
|
-
São **
|
|
22
|
+
São **159 ferramentas**: desenho, animação, diagramas, mapas, tipografia, física, edição de imagens, visualização de dados e exportação:
|
|
23
23
|
|
|
24
24
|
- Criar texto, formas, geometria e gráficos complexos
|
|
25
25
|
- Animar com **relações** declarativas em vez de keyframes
|
package/README.zh-CN.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
PinePaper MCP 服务器让 AI 助手通过 MCP 协议在 [PinePaper Studio](https://pinepaper.studio) 中创建和驱动图形动画。兼容任何支持 MCP 工具调用的 AI(Claude、GPT、Gemini、本地模型等)。
|
|
21
21
|
|
|
22
|
-
服务器提供 **
|
|
22
|
+
服务器提供 **159 个工具**,覆盖绘图、动画、图表、地图、排版、物理、图像编辑、数据可视化与导出:
|
|
23
23
|
|
|
24
24
|
- 创建文本、形状、几何图形与复杂图稿
|
|
25
25
|
- 用行为驱动的**关系(relations)**做动画,而不是逐帧关键帧
|
package/dist/build-info.json
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* FxTool's ITEM_TYPE_MAP and type classes (anchor, description, parentType,
|
|
5
5
|
* mcpTool, mcpAction), read from the loaded module.
|
|
6
6
|
*
|
|
7
|
-
* Source: FxTool origin/main
|
|
7
|
+
* Source: FxTool origin/main 9dd578afaa83c6286bfa2f554e8665407be400e1
|
|
8
8
|
* js/ontology/Vocabulary.js
|
|
9
|
-
* sha256:
|
|
9
|
+
* sha256: 48fb80f82d3d3220
|
|
10
10
|
*
|
|
11
11
|
* vocabulary.ts merges these over its hand-written port: the engine's map
|
|
12
12
|
* wins where the two disagree, and a class the port lacks is added.
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* FxTool's ITEM_TYPE_MAP and type classes (anchor, description, parentType,
|
|
5
5
|
* mcpTool, mcpAction), read from the loaded module.
|
|
6
6
|
*
|
|
7
|
-
* Source: FxTool origin/main
|
|
7
|
+
* Source: FxTool origin/main 9dd578afaa83c6286bfa2f554e8665407be400e1
|
|
8
8
|
* js/ontology/Vocabulary.js
|
|
9
|
-
* sha256:
|
|
9
|
+
* sha256: 48fb80f82d3d3220
|
|
10
10
|
*
|
|
11
11
|
* vocabulary.ts merges these over its hand-written port: the engine's map
|
|
12
12
|
* wins where the two disagree, and a class the port lacks is added.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA+B/C,eAAO,MAAM,cAAc,6kbAyK+G,CAAC;AAW3I,eAAO,MAAM,eAAe,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA+B/C,eAAO,MAAM,cAAc,6kbAyK+G,CAAC;AAW3I,eAAO,MAAM,eAAe,EAAE,IAAI,EA6tRjC,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE5D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,CAO3D;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9D;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,EAAE,CAQrE"}
|
|
@@ -261,12 +261,12 @@ COMMON PRESETS:
|
|
|
261
261
|
- hd-landscape: 1920x1080
|
|
262
262
|
- hd-portrait: 1080x1920
|
|
263
263
|
|
|
264
|
-
Max canvas size:
|
|
264
|
+
Max canvas size: 16384 per side (a 12000 px DOOH or projection canvas fits); above 8192 Safari / iOS may not render it, Chrome and Firefox do. For wedding invitations, event cards, or detailed designs, use at least 1080x1080 or larger.`,
|
|
265
265
|
inputSchema: {
|
|
266
266
|
type: 'object',
|
|
267
267
|
properties: {
|
|
268
|
-
width: { type: 'number', description: 'Canvas width in pixels (100-
|
|
269
|
-
height: { type: 'number', description: 'Canvas height in pixels (100-
|
|
268
|
+
width: { type: 'number', description: 'Canvas width in pixels (100-16384)' },
|
|
269
|
+
height: { type: 'number', description: 'Canvas height in pixels (100-16384)' },
|
|
270
270
|
preset: {
|
|
271
271
|
type: 'string',
|
|
272
272
|
description: 'Optional preset name',
|
|
@@ -732,6 +732,8 @@ Use the collage group's id for palette/collageStyle; use a child letter's id for
|
|
|
732
732
|
isDecorative: { type: 'boolean', description: 'Mark as decorative/non-interactive' },
|
|
733
733
|
},
|
|
734
734
|
},
|
|
735
|
+
atTime: { type: 'number', minimum: 0, description: 'AUTO-KEY: instead of a static edit, write these properties as keyframes at this time (seconds) — the same as a user dragging with auto-key on. Eased from the previous value; other keys and other properties\' curves are kept. "At 4 s make it orange" is { properties: { fillColor: "orange" }, atTime: 4 }.' },
|
|
736
|
+
easing: { type: 'string', description: 'atTime: easing of the segment arriving at the new key (default linear).' },
|
|
735
737
|
},
|
|
736
738
|
required: ['itemId', 'properties'],
|
|
737
739
|
},
|
|
@@ -1152,6 +1154,8 @@ EXAMPLES:
|
|
|
1152
1154
|
type: 'number',
|
|
1153
1155
|
description: 'Maximum height constraint in pixels',
|
|
1154
1156
|
},
|
|
1157
|
+
maxEdge: { anyOf: [{ type: 'integer', minimum: 1 }, { type: 'string', enum: ['native'] }], description: "The longest edge the studio STORES the image at (px); 'native' keeps every pixel. Default: the studio's cap, which follows the canvas on desktop. The result says when the image was stored smaller than its source." },
|
|
1158
|
+
nativeSize: { type: 'boolean', description: 'Place the image at its source footprint even if it was stored smaller.' },
|
|
1155
1159
|
mask: {
|
|
1156
1160
|
type: 'string',
|
|
1157
1161
|
enum: ['circle', 'rounded', 'hexagon', 'star'],
|
|
@@ -1729,6 +1733,47 @@ EXAMPLES:
|
|
|
1729
1733
|
required: ['action'],
|
|
1730
1734
|
},
|
|
1731
1735
|
},
|
|
1736
|
+
{
|
|
1737
|
+
name: 'pinepaper_beat_cuts',
|
|
1738
|
+
annotations: { title: 'Beat-Snapped Cuts', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
1739
|
+
description: `Cut on the music: analyse a track's beats (or take beat times you already have), fit a beat grid, and return cut points on every beat, every bar, or every N beats — optionally splitting a video or audio clip at each one.
|
|
1740
|
+
|
|
1741
|
+
- source: the music — an upload id, URL, data: URL or local file path. Or beats: [seconds] to skip the analysis.
|
|
1742
|
+
- every: 'beat' (default) | 'bar' | N beats. beatsPerBar (default 4). range: [from, to] seconds.
|
|
1743
|
+
- bpm: the tempo, if you know it (the grid's phase is still fitted to the music). Otherwise the studio's detection and its usual confusions (double, half, 3:4, 4:3 …) are scored against the music and the best is used; bpmHint: [min, max] keeps the choice in a range. The result lists the candidates, and says lowConfidence with a warning when the tempo is uncertain — pass bpm then.
|
|
1744
|
+
- clipId: split this clip at each cut, in order; cuts outside the clip are skipped and listed.
|
|
1745
|
+
|
|
1746
|
+
Returns cuts (seconds), the grid (bpm, phase, period, confidence) and, with clipId, the pieces' ids.`,
|
|
1747
|
+
inputSchema: {
|
|
1748
|
+
type: 'object',
|
|
1749
|
+
properties: {
|
|
1750
|
+
source: { type: 'string' },
|
|
1751
|
+
beats: { type: 'array', items: { type: 'number' } },
|
|
1752
|
+
bpm: { type: 'number' },
|
|
1753
|
+
bpmHint: { type: 'array', items: { type: 'number' }, minItems: 2, maxItems: 2, description: '[min, max] bpm to choose within.' },
|
|
1754
|
+
includeOnsets: { type: 'boolean', description: 'Also return the detected onsets (for diagnosing a tempo pick).' },
|
|
1755
|
+
every: { anyOf: [{ type: 'string', enum: ['beat', 'bar'] }, { type: 'integer', minimum: 1, maximum: 64 }] },
|
|
1756
|
+
beatsPerBar: { type: 'integer', minimum: 1, maximum: 16 },
|
|
1757
|
+
range: { type: 'array', items: { type: 'number' }, minItems: 2, maxItems: 2 },
|
|
1758
|
+
clipId: { type: 'string' },
|
|
1759
|
+
},
|
|
1760
|
+
},
|
|
1761
|
+
},
|
|
1762
|
+
{
|
|
1763
|
+
name: 'pinepaper_query_mutations',
|
|
1764
|
+
annotations: { title: 'Query Property Keyframes', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1765
|
+
description: `A property's values over time: the item's keyframe series ({t, frame, value, easing} per key), for one property or all, optionally within [from, to] seconds. The read side of modify_item { atTime } (auto-key): "what changed at 4 s?", "show the colour over time". It reads the item's keyframe track; it does not yet say WHO made each change or the value before it — that needs the studio's mutation log.`,
|
|
1766
|
+
inputSchema: {
|
|
1767
|
+
type: 'object',
|
|
1768
|
+
properties: {
|
|
1769
|
+
itemId: { type: 'string' },
|
|
1770
|
+
property: { type: 'string', description: 'One property; all animated properties when omitted.' },
|
|
1771
|
+
range: { type: 'array', items: { type: 'number' }, minItems: 2, maxItems: 2, description: '[from, to] seconds.' },
|
|
1772
|
+
fps: { type: 'number', description: 'For the frame numbers (default 30).' },
|
|
1773
|
+
},
|
|
1774
|
+
required: ['itemId'],
|
|
1775
|
+
},
|
|
1776
|
+
},
|
|
1732
1777
|
{
|
|
1733
1778
|
name: 'pinepaper_accessibility_check',
|
|
1734
1779
|
annotations: {
|
|
@@ -1750,11 +1795,96 @@ EXAMPLE: { checks: ["contrast", "flash"], duration: 6, fps: 20 }`,
|
|
|
1750
1795
|
type: 'object',
|
|
1751
1796
|
properties: {
|
|
1752
1797
|
checks: { type: 'array', items: { type: 'string', enum: ['contrast', 'flash'] }, description: 'Which checks (default both).' },
|
|
1753
|
-
duration: { type: 'number', exclusiveMinimum: 0, maximum: 120, description: '
|
|
1798
|
+
duration: { type: 'number', exclusiveMinimum: 0, maximum: 120, description: 'Seconds of the timeline to sample (default 5): flash samples it at fps; contrast at 0 s, inside each text lifetime, at keyframe times and every second.' },
|
|
1754
1799
|
fps: { type: 'integer', minimum: 10, maximum: 60, description: 'flash: samples per second (default 20).' },
|
|
1755
1800
|
},
|
|
1756
1801
|
},
|
|
1757
1802
|
},
|
|
1803
|
+
{
|
|
1804
|
+
name: 'pinepaper_generate',
|
|
1805
|
+
annotations: { title: 'Generate Image (cloud)', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
1806
|
+
description: `Generate images with an AI model in the PinePaper cloud, and optionally place the first one on the canvas. CHARGED per output — price it first with pinepaper_generate_estimate (free).
|
|
1807
|
+
|
|
1808
|
+
Needs a service-account key in PINEPAPER_API_KEY (pp_sa_…, render:create scope). It is an internal beta enabled per organisation: without it the result says "not enabled for your organisation", and nothing is charged. Every refusal says whether anything was charged.
|
|
1809
|
+
|
|
1810
|
+
- model or useCase: a model id from pinepaper_generate_estimate {listModels: true}, or a use case and the cloud picks its default (hero stills, plates, text in the image, character-consistent edits).
|
|
1811
|
+
- input: { prompt, aspect ('16:9' | '9:16' | '1:1' | '4:5'), n (1-4), seed?, negativePrompt?, imageUrls? (https references for edit models) }.
|
|
1812
|
+
- brief / designRef: always passed on; the cloud records each generation against the design.
|
|
1813
|
+
- place: 'cover' (fill the canvas, centred; default when true) or 'contain' — places the first asset: an image as an image item, a video as a video layer (with its durationSeconds). The fit uses the asset's delivered size, not the requested aspect.
|
|
1814
|
+
- timeoutSec: how long to wait (default 180). A job that outlives it keeps running and is only charged if it delivers; collect it with pinepaper_generate_status.
|
|
1815
|
+
|
|
1816
|
+
WORDS ARE VECTOR: give words as input.text [{content, role?: headline|subhead|caption|cta|label, font?}]. The model makes a text-free plate; the words come back as textLayers (plus a hint), and with place they are added as real, editable text over it: headline top-left (Anton by default), subhead below, caption / cta bottom-left, label top-right, inside title-safe, each contrast-checked against the plate (a dark scrim is added only where it falls short of WCAG 4.5:1, or 3:1 for large text). Their item ids are in placement.text.
|
|
1817
|
+
|
|
1818
|
+
The result: assets [{assetId, ref, width, height}] — the sizes the files HAVE (a model may pick its own size for an aspect), chargedUsd, and any model notes (e.g. a SynthID watermark) to pass on.`,
|
|
1819
|
+
inputSchema: {
|
|
1820
|
+
type: 'object',
|
|
1821
|
+
properties: {
|
|
1822
|
+
model: { type: 'string' },
|
|
1823
|
+
useCase: { type: 'string' },
|
|
1824
|
+
input: {
|
|
1825
|
+
type: 'object',
|
|
1826
|
+
properties: {
|
|
1827
|
+
prompt: { type: 'string' },
|
|
1828
|
+
aspect: { type: 'string', enum: ['16:9', '9:16', '1:1', '4:5'] },
|
|
1829
|
+
n: { type: 'integer', minimum: 1, maximum: 4 },
|
|
1830
|
+
seed: { type: 'integer' },
|
|
1831
|
+
negativePrompt: { type: 'string' },
|
|
1832
|
+
imageUrls: { type: 'array', items: { type: 'string' }, maxItems: 14, description: 'Reference / start-frame images: https URLs, or your own generated images as their ref "/scene-assets/<id>" (chain a still into a video or a character edit).' },
|
|
1833
|
+
seconds: { type: 'number', exclusiveMinimum: 0, maximum: 60, description: 'Video models: clip length; each model allows its own lengths (listModels).' },
|
|
1834
|
+
text: { type: 'array', maxItems: 12, items: { type: 'object', properties: { content: { type: 'string' }, role: { type: 'string', enum: ['headline', 'subhead', 'caption', 'cta', 'label'] }, font: { type: 'string' } }, required: ['content'] }, description: 'Words for the design. The model never draws them: the plate comes back text-free and these return as textLayers — with place, laid out as real PinePaper text.' },
|
|
1835
|
+
allowText: { type: 'boolean', description: 'Let the MODEL draw text — eval-tier models only (e.g. ideogram-v3); refused (422) elsewhere. Prefer text.' },
|
|
1836
|
+
},
|
|
1837
|
+
required: ['prompt'],
|
|
1838
|
+
},
|
|
1839
|
+
brief: { type: 'string' },
|
|
1840
|
+
designRef: { type: 'object', properties: { kind: { type: 'string' }, id: { type: 'string' } }, required: ['kind', 'id'] },
|
|
1841
|
+
place: { anyOf: [{ type: 'boolean' }, { type: 'string', enum: ['cover', 'contain'] }] },
|
|
1842
|
+
timeoutSec: { type: 'integer', minimum: 10, maximum: 1800 },
|
|
1843
|
+
},
|
|
1844
|
+
required: ['input'],
|
|
1845
|
+
},
|
|
1846
|
+
},
|
|
1847
|
+
{
|
|
1848
|
+
name: 'pinepaper_generate_estimate',
|
|
1849
|
+
annotations: { title: 'Estimate Generation (free)', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1850
|
+
description: `Free: price a pinepaper_generate call before making it, or list the models. { listModels: true } returns every model you may use with its price per output, use cases, licence notes and the defaults per use case; { model | useCase, input } returns the estimate for that request. Needs PINEPAPER_API_KEY, like pinepaper_generate.`,
|
|
1851
|
+
inputSchema: {
|
|
1852
|
+
type: 'object',
|
|
1853
|
+
properties: {
|
|
1854
|
+
model: { type: 'string' },
|
|
1855
|
+
useCase: { type: 'string' },
|
|
1856
|
+
input: {
|
|
1857
|
+
type: 'object',
|
|
1858
|
+
properties: {
|
|
1859
|
+
prompt: { type: 'string' },
|
|
1860
|
+
aspect: { type: 'string', enum: ['16:9', '9:16', '1:1', '4:5'] },
|
|
1861
|
+
n: { type: 'integer', minimum: 1, maximum: 4 },
|
|
1862
|
+
seed: { type: 'integer' },
|
|
1863
|
+
negativePrompt: { type: 'string' },
|
|
1864
|
+
imageUrls: { type: 'array', items: { type: 'string' }, maxItems: 14, description: 'Reference / start-frame images: https URLs, or your own generated images as their ref "/scene-assets/<id>" (chain a still into a video or a character edit).' },
|
|
1865
|
+
seconds: { type: 'number', exclusiveMinimum: 0, maximum: 60, description: 'Video models: clip length; each model allows its own lengths (listModels).' },
|
|
1866
|
+
text: { type: 'array', maxItems: 12, items: { type: 'object', properties: { content: { type: 'string' }, role: { type: 'string', enum: ['headline', 'subhead', 'caption', 'cta', 'label'] }, font: { type: 'string' } }, required: ['content'] }, description: 'Words for the design. The model never draws them: the plate comes back text-free and these return as textLayers — with place, laid out as real PinePaper text.' },
|
|
1867
|
+
allowText: { type: 'boolean', description: 'Let the MODEL draw text — eval-tier models only (e.g. ideogram-v3); refused (422) elsewhere. Prefer text.' },
|
|
1868
|
+
},
|
|
1869
|
+
required: ['prompt'],
|
|
1870
|
+
},
|
|
1871
|
+
listModels: { type: 'boolean' },
|
|
1872
|
+
},
|
|
1873
|
+
},
|
|
1874
|
+
},
|
|
1875
|
+
{
|
|
1876
|
+
name: 'pinepaper_generate_status',
|
|
1877
|
+
annotations: { title: 'Generation Status', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1878
|
+
description: `Collect a pinepaper_generate job that outlived its timeoutSec: its status, and when done its assets and chargedUsd. place: 'cover' | 'contain' places the first image, as pinepaper_generate does.`,
|
|
1879
|
+
inputSchema: {
|
|
1880
|
+
type: 'object',
|
|
1881
|
+
properties: {
|
|
1882
|
+
jobId: { type: 'string' },
|
|
1883
|
+
place: { anyOf: [{ type: 'boolean' }, { type: 'string', enum: ['cover', 'contain'] }] },
|
|
1884
|
+
},
|
|
1885
|
+
required: ['jobId'],
|
|
1886
|
+
},
|
|
1887
|
+
},
|
|
1758
1888
|
{
|
|
1759
1889
|
name: 'pinepaper_render_batch',
|
|
1760
1890
|
annotations: {
|
|
@@ -2043,15 +2173,18 @@ EXAMPLE: { times: [0, 0.5, 1, 1.5, 2], seed: 42 }`,
|
|
|
2043
2173
|
description: `Bring VIDEO and AUDIO onto the canvas from a URL, and control playback. Uploaded video is a first-class canvas item (drag, scale, animate, export like any shape); audio rides the timeline.
|
|
2044
2174
|
|
|
2045
2175
|
ACTIONS:
|
|
2046
|
-
- upload_video: { url (required), position?, scale
|
|
2047
|
-
- upload_audio: { url (required), volume? (0–1, default 1), loop?, muted?, timeOffset? } → { id, registryId, duration, name }. Pass loop EXPLICITLY — loop:true for a music bed, loop:false for a voice-over or sting; when omitted, the studio's own default applies and differs between builds.
|
|
2176
|
+
- upload_video: { url (required), position?, fit? ('contain' default | 'cover' | 'none' = source pixels), scale? (a multiplier on that fit — with fit 'none', on the source pixels), timeOffset? (timeline start, s) or atPlayhead?: true (start at the current playback time), clipInPoint?, clipOutPoint? (trim, s) } → { id, duration, width, height, name }
|
|
2177
|
+
- upload_audio: { url (required), volume? (0–1, default 1), loop?, muted?, timeOffset? or atPlayhead? } → { id, registryId, duration, name }. Pass loop EXPLICITLY — loop:true for a music bed, loop:false for a voice-over or sting; when omitted, the studio's own default applies and differs between builds.
|
|
2048
2178
|
- list: → all media [{ id, kind, duration, … }]
|
|
2049
2179
|
- remove: { id } → removed boolean
|
|
2050
2180
|
- set_playback_rate: { id, rate (0.25–4) } → applies to video or audio
|
|
2051
|
-
- set_clip: { id, inPoint, outPoint (media-time s, outPoint > inPoint) } → re-trim an ALREADY-uploaded clip (video or audio)
|
|
2181
|
+
- set_clip: { id, inPoint, outPoint (media-time s, outPoint > inPoint), timeOffset? (canvas s: also MOVE the clip to start there) } → re-trim an ALREADY-uploaded clip (video or audio). A studio that cannot move clips refuses timeOffset rather than ignoring it.
|
|
2182
|
+
- split: { id, at (canvas s) } → cut a clip in two: { leftId, rightId, leftMediaId, rightMediaId, at }. The first half keeps its id. Refused (not claimed) where the studio cannot split or the time is outside the clip.
|
|
2183
|
+
- add_transition: { fromItemId (ends at the cut), toItemId (starts at it), transition?: { type: 'crossfade'|'dip', seconds, color } } → the same in preview and export. Split a clip, then transition between its halves, or join two clips that meet.
|
|
2184
|
+
- For an IMAGE on the timeline, use pinepaper_import_image with bornAt / ttl (seconds on screen).
|
|
2052
2185
|
|
|
2053
2186
|
NOTES:
|
|
2054
|
-
-
|
|
2187
|
+
- The server fetches the URL (or reads a local path / data: URL) and hands the page the bytes, so it does not need to be CORS-permitted.
|
|
2055
2188
|
- Use the returned id with set_playback_rate / set_clip / remove, and (for video) modify/animate it like any item.
|
|
2056
2189
|
|
|
2057
2190
|
VIDEO EDITING:
|
|
@@ -2065,14 +2198,16 @@ EXAMPLE: { action: 'upload_video', url: 'https://…/clip.mp4', scale: 0.5, time
|
|
|
2065
2198
|
inputSchema: {
|
|
2066
2199
|
type: 'object',
|
|
2067
2200
|
properties: {
|
|
2068
|
-
action: { type: 'string', enum: ['upload_video', 'upload_audio', 'list', 'remove', 'set_playback_rate', 'set_clip', 'set_time_remap', 'speed_ramp', 'match_cut', 'apply_track_matte', 'stop_live_matte'], description: "Media action" },
|
|
2201
|
+
action: { type: 'string', enum: ['upload_video', 'upload_audio', 'list', 'remove', 'set_playback_rate', 'set_clip', 'split', 'add_transition', 'set_time_remap', 'speed_ramp', 'match_cut', 'apply_track_matte', 'stop_live_matte'], description: "Media action" },
|
|
2202
|
+
transition: { type: 'object', properties: { type: { type: 'string', enum: ['crossfade', 'dip'] }, seconds: { type: 'number', exclusiveMinimum: 0, maximum: 10 }, color: { type: 'string' } }, description: "add_transition: { type ('crossfade' default | 'dip'), seconds, color (dip) }." },
|
|
2203
|
+
atPlayhead: { type: 'boolean', description: 'upload_video / upload_audio: start at the current playback time (instead of timeOffset).' },
|
|
2069
2204
|
remapTrack: { type: 'array', items: { type: 'object', properties: { time: { type: 'number' }, value: { type: 'number' }, easing: { type: 'string' } }, required: ['time', 'value'] }, description: 'set_time_remap: canvas-seconds → source-seconds curve (≥2 points). null clears the remap.' },
|
|
2070
2205
|
segments: { type: 'array', items: { type: 'object', properties: { duration: { type: 'number' }, speed: { type: 'number' } }, required: ['duration', 'speed'] }, description: 'speed_ramp: consecutive {duration, speed} segments. speed 0 = freeze frame, negative = reverse.' },
|
|
2071
2206
|
fromItemId: { type: 'string', description: 'match_cut: outgoing shot item id.' },
|
|
2072
2207
|
toItemId: { type: 'string', description: 'match_cut: incoming shot item id.' },
|
|
2073
2208
|
subject: { type: 'string', enum: ['detect', 'bounds'], description: "match_cut: subject source — 'detect' (on-device DETR, needs consent on first use) or 'bounds'." },
|
|
2074
2209
|
label: { type: 'string', description: 'match_cut: narrow detection to one class ("person") when the biggest object is not the subject.' },
|
|
2075
|
-
at: { type: 'number', description: 'match_cut: cut time in seconds (default 0).' },
|
|
2210
|
+
at: { type: 'number', description: 'match_cut: cut time in seconds (default 0). split: the canvas time to cut at (required).' },
|
|
2076
2211
|
settle: { type: 'number', description: 'match_cut: seconds to relax to natural framing (default 0.8).' },
|
|
2077
2212
|
fade: { type: 'number', description: 'match_cut: crossfade seconds; 0 = hard cut (default 0.12).' },
|
|
2078
2213
|
consent: { type: 'boolean', description: 'match_cut: allow the detection model download (a first run without it returns needsConsent instead of downloading silently).' },
|
|
@@ -2088,8 +2223,9 @@ EXAMPLE: { action: 'upload_video', url: 'https://…/clip.mp4', scale: 0.5, time
|
|
|
2088
2223
|
inPoint: { type: 'number', description: 'Clip in-point (media-time s) — set_clip.' },
|
|
2089
2224
|
outPoint: { type: 'number', description: 'Clip out-point (media-time s, > inPoint) — set_clip.' },
|
|
2090
2225
|
position: { type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' } }, description: 'Canvas position — upload_video.' },
|
|
2091
|
-
scale: { type: 'number', description: '
|
|
2092
|
-
|
|
2226
|
+
scale: { type: 'number', description: "upload_video: a multiplier on the fit (contain by default), not on the source pixels; with fit: 'none', of the source pixels." },
|
|
2227
|
+
fit: { type: 'string', enum: ['contain', 'cover', 'none'], description: "upload_video: size before scale — 'contain' (default), 'cover', or 'none' (source pixels)." },
|
|
2228
|
+
timeOffset: { type: 'number', description: 'Timeline start offset (s) — upload_video / upload_audio; set_clip: move the clip to start here.' },
|
|
2093
2229
|
clipInPoint: { type: 'number', description: 'Trim in-point (s) — upload_video.' },
|
|
2094
2230
|
clipOutPoint: { type: 'number', description: 'Trim out-point (s) — upload_video.' },
|
|
2095
2231
|
volume: { type: 'number', description: 'Volume 0–1 (default 1) — upload_audio.' },
|
|
@@ -2630,6 +2766,7 @@ render_soundtrack mixes every placed sound to a WAV and writes it to a file. It
|
|
|
2630
2766
|
noiseFreq: { type: 'number', description: 'define_percussion / define_sfx: noise band centre in Hz.' },
|
|
2631
2767
|
hz: { type: 'number', description: 'define_percussion / define_sfx: base frequency in Hz.' },
|
|
2632
2768
|
pitch: { type: 'object', description: 'define_percussion / define_sfx: { from, tau } pitch glide. The glide IS the drum — omit it and a kick comes out a beep.' },
|
|
2769
|
+
duration: { type: 'number', description: 'render_soundtrack: seconds to render (options.duration also works; this wins if both are given). Without either, the studio uses the timeline length (3 s when there is none).' },
|
|
2633
2770
|
sampleRate: { type: 'number', description: 'render_soundtrack: samples per second (default 48000).' },
|
|
2634
2771
|
bitDepth: { type: 'number', enum: [16, 32], description: 'render_soundtrack: 16 (default) or 32-bit float.' },
|
|
2635
2772
|
note: { type: 'string', description: "play_tone: scientific pitch, e.g. 'A4'." },
|
|
@@ -3571,6 +3708,10 @@ EXAMPLE — Reveal at 2s, skip first second of keyframe data, end at 4s of keyfr
|
|
|
3571
3708
|
type: 'number',
|
|
3572
3709
|
description: 'Stop at N seconds into the keyframe data (tail trim). Default: lastKeyframeTime.',
|
|
3573
3710
|
},
|
|
3711
|
+
append: {
|
|
3712
|
+
type: 'boolean',
|
|
3713
|
+
description: 'Add these keys to the item\'s existing track (same-time keys merge, new values win) instead of replacing it — e.g. a button press after an entrance. Without it, a second call replaces the track. result.track says whether the track was appended to or replaced; studios without merge replace, and say so.',
|
|
3714
|
+
},
|
|
3574
3715
|
},
|
|
3575
3716
|
required: ['itemId', 'keyframes'],
|
|
3576
3717
|
},
|
|
@@ -4901,7 +5042,9 @@ ACTIONS:
|
|
|
4901
5042
|
- update_from_instance: Promote an instance's edits back into the master. Params: instanceId
|
|
4902
5043
|
- detach: Make an instance an ordinary independent item. Params: instanceId
|
|
4903
5044
|
|
|
4904
|
-
Overrides are the point: an instance can differ from its master and still receive master updates
|
|
5045
|
+
Overrides are the point: an instance can differ from its master and still receive master updates.
|
|
5046
|
+
|
|
5047
|
+
Instances carry the master's LOOK (geometry, style, text), not its animation: instantiate and sync copy what the master is, not its keyframes or animations. To animate instances, animate each one (keyframe_animate on its instanceId, or stagger across them).`,
|
|
4905
5048
|
inputSchema: {
|
|
4906
5049
|
type: 'object',
|
|
4907
5050
|
properties: {
|
|
@@ -7739,7 +7882,7 @@ NOTE: For diagrams (flowcharts, UML), use pinepaper_create_diagram_shape + pinep
|
|
|
7739
7882
|
|
|
7740
7883
|
⚠️ EVERY operation executes LIVE on the canvas. Calling this twice DOUBLES all items. Call ONCE per pipeline.
|
|
7741
7884
|
|
|
7742
|
-
⚠️ SIZING: All positions/sizes MUST fit within the canvas. start_job returns canvasSize. Keep items within 5%-95% of canvas width/height. Max canvas:
|
|
7885
|
+
⚠️ SIZING: All positions/sizes MUST fit within the canvas. start_job returns canvasSize. Keep items within 5%-95% of canvas width/height. Max canvas: 16384 per side (above 8192, Safari / iOS may fail).
|
|
7743
7886
|
|
|
7744
7887
|
ONTOLOGY PREFLIGHT: Before code generation, this tool validates itemType, relationType, effectType, and generatorName against the canonical PinePaper vocabulary. A typo (e.g. "circel") returns a structured VALIDATION_ERROR with the operation index, the offending field, the canonical valid list, and a suggested fix — fix and retry rather than guessing. Pass skipValidation: true to bypass when intentionally using experimental vocabulary.
|
|
7745
7888
|
|
|
@@ -7826,8 +7969,8 @@ EXAMPLE — Animated sky scene with timed reveals:
|
|
|
7826
7969
|
description: 'Operation type',
|
|
7827
7970
|
},
|
|
7828
7971
|
// Canvas setup
|
|
7829
|
-
width: { type: 'number', description: 'Canvas width for set_canvas_size (100-
|
|
7830
|
-
height: { type: 'number', description: 'Canvas height for set_canvas_size (100-
|
|
7972
|
+
width: { type: 'number', description: 'Canvas width for set_canvas_size (100-16384)' },
|
|
7973
|
+
height: { type: 'number', description: 'Canvas height for set_canvas_size (100-16384)' },
|
|
7831
7974
|
preset: { type: 'string', description: 'Canvas preset for set_canvas_size' },
|
|
7832
7975
|
backgroundColor: { type: 'string', description: 'For set_background: hex color' },
|
|
7833
7976
|
generatorName: {
|
|
@@ -8050,6 +8193,8 @@ VERIFY MOTION BEFORE YOU RENDER. An export takes seconds to minutes and shows yo
|
|
|
8050
8193
|
alphaQuantizer: { type: 'integer', minimum: 0, maximum: 63, description: 'webm with transparent: alpha-stream quality, 0 = lossless … 63.' },
|
|
8051
8194
|
loop: { anyOf: [{ type: 'boolean' }, { type: 'integer', minimum: 0, maximum: 1000 }], description: 'gif / apng: true = loop forever, false / 0 / 1 = play once, n = play n times (email clients often want a few plays, not forever). Refused on video formats — see SEAMLESS LOOPS.' },
|
|
8052
8195
|
broadcast: { type: 'boolean', description: 'mp4 only: broadcast-safe — BT.709, limited range (16-235), tagged bt709, constant bitrate with an 8 Mbps floor at 720p+ (4 below). result.video reports what the encoder did.' },
|
|
8196
|
+
frames: { type: 'integer', minimum: 1, maximum: 36000, description: 'Animated formats: exactly this many frames instead of duration. A duration makes ceil(duration x fps) frames (7.91667 s at 24 fps is 191, not 190), so use frames for frame-exact segments.' },
|
|
8197
|
+
deterministic: { type: 'boolean', description: 'mp4 / webm: byte-identical files for the same scene (pins the container timestamps), so exports can be checksummed or cached by hash.' },
|
|
8053
8198
|
broadcastHeadroom: { type: 'integer', minimum: 0, maximum: 40, description: 'mp4 with broadcast only, default 12: luma codes kept clear at both ends, so encoder ringing stays legal (12 measured clean on hard edges; 4 = ~100x fewer out-of-range samples, 12 = ~1000x; never zero). Fidelity raises luma_out_of_range with the legaliser command when any remain.' },
|
|
8054
8199
|
bitrate: { type: 'integer', minimum: 100000, maximum: 200000000, description: 'mp4 / webm: target bits/s, replacing the quality-derived one. The browser encoder treats it as a CEILING; result.video.achievedBitrate is what it produced.' },
|
|
8055
8200
|
minBitrate: { type: 'integer', minimum: 100000, maximum: 200000000, description: 'mp4 / webm: a floor; a miss is a fidelity warning naming the re-encode a delivery spec needs.' },
|
|
@@ -8075,7 +8220,7 @@ VERIFY MOTION BEFORE YOU RENDER. An export takes seconds to minutes and shows yo
|
|
|
8075
8220
|
properties: {
|
|
8076
8221
|
x: { type: 'number' }, y: { type: 'number' },
|
|
8077
8222
|
width: { type: 'number', exclusiveMinimum: 0 }, height: { type: 'number', exclusiveMinimum: 0 },
|
|
8078
|
-
outputWidth: { type: 'integer', minimum: 1, maximum:
|
|
8223
|
+
outputWidth: { type: 'integer', minimum: 1, maximum: 16384 }, outputHeight: { type: 'integer', minimum: 1, maximum: 16384 },
|
|
8079
8224
|
excludeForeign: { type: 'boolean', description: 'Default true: an item reaching into the region but centred outside it (a neighbouring card overflow) is left out of this image; result.excludedItems names them. false renders everything that touches the region.' },
|
|
8080
8225
|
},
|
|
8081
8226
|
required: ['x', 'y', 'width', 'height'],
|
|
@@ -8107,8 +8252,8 @@ VERIFY MOTION BEFORE YOU RENDER. An export takes seconds to minutes and shows yo
|
|
|
8107
8252
|
duration: {
|
|
8108
8253
|
type: 'number',
|
|
8109
8254
|
minimum: 0.5,
|
|
8110
|
-
maximum:
|
|
8111
|
-
description: 'Video duration in seconds for mp4/webm/gif (default 5). Max
|
|
8255
|
+
maximum: 600,
|
|
8256
|
+
description: 'Video duration in seconds for mp4/webm/gif (default 5). Max 600 for mp4/webm (past about a minute the file is paged back from the studio\'s export store); GIF is capped at 15 because it has no bitrate target, so size scales with frames × dimensions — use mp4/webm for longer clips. The file has ceil(duration × fps) frames — for an exact count use frames instead. Static formats ignore this. If you set play_timeline to N seconds, pass the same N here.',
|
|
8112
8257
|
},
|
|
8113
8258
|
},
|
|
8114
8259
|
// Nothing is required: platform defaults to 'auto', which is the canvas's
|