mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 17:32:42 -06:00
Merge pull request #6557 from dotCooCoo/feat/script-alert-confirm-prompt
Scripts: alert, confirm and prompt open dialogs with Stop, and headless runs take their answers from script.run
This commit is contained in:
+55
-5
@@ -1569,6 +1569,8 @@ app through the global object `vc`, and writes to the Script Console and runs ot
|
||||
missing file and a refused path throw errors the script can catch.
|
||||
- `$.fileName` is the file being run, which is the file `$.evalFile` is running while it runs, and is empty for a
|
||||
script given as `source`. `$.includePath` is the current `#includepath` list, separated by `;`.
|
||||
- `alert(message[, title, errorIcon])`, `confirm(message[, noAsDflt, title])` and `prompt(message, preset[, title])`
|
||||
open a dialog, described below. `vc.api.has("dialogs")` is true.
|
||||
- `vc.args` is the `args` object.
|
||||
- `vc.api.version` is `"1.0"`, and `vc.api.has(feature)` says whether the API has a feature.
|
||||
|
||||
@@ -1634,16 +1636,18 @@ VectorCraft sets these limits itself:
|
||||
| `args` as JSON | 1 MiB |
|
||||
| Log | 10,000 entries and 4 MiB |
|
||||
| Script Console | 2,048 lines and 1 MiB of text; 4,096 bytes a line; 256 bytes of a script's name |
|
||||
| A dialog's message, title and prompt preset | 16 KiB, 256 bytes and 16 KiB |
|
||||
| `answers` | 10,000 answers and 1 MiB as JSON |
|
||||
| `dialogs` in the report | 10,000 dialogs and 1 MiB as JSON |
|
||||
| Growth before a person is asked | 100,000 objects and 512 MiB of new document data |
|
||||
|
||||
In the app, a script past the growth limit stops at a question to continue or to stop and undo. Stop, Escape and
|
||||
`ui.dialog.cancel` all stop the run. A run with nobody to ask, such as a call over MCP or the command line, ends
|
||||
with an error at that limit. The headless reply is `{ok: true, name, changed, written, log, fuelUsed, hostCalls,
|
||||
runTimeMs, timingAvailable, hostCallCounts, slowestCommands, console}`. In the app the reply is `{running: true,
|
||||
name}`, and the report appears later as `scriptReport` in `ui.inspect`. The report of a failed run has the same
|
||||
fields after `kind`, `message`, `line`, `column`, `file` (when the error is in another file than the script) and
|
||||
`fuelLeft`. `answers` takes only an empty object, since scripts
|
||||
have no prompts yet.
|
||||
runTimeMs, timingAvailable, hostCallCounts, slowestCommands, console, dialogs, dialogCount, dialogsTruncated}`. In
|
||||
the app the reply is `{running: true, name}`, and the report appears later as `scriptReport` in `ui.inspect`. The
|
||||
report of a failed run has the same fields after `kind`, `message`, `line`, `column`, `file` (when the error is in
|
||||
another file than the script) and `fuelLeft`.
|
||||
|
||||
- `runTimeMs` is the time the script ran, its commands included. Waits between frames and for a person's answer are
|
||||
left out. `timingAvailable` is false on the web, where `runTimeMs` is 0.
|
||||
@@ -1651,6 +1655,11 @@ have no prompts yet.
|
||||
- `slowestCommands` lists at most 5 commands as `{id, calls, totalMs, maxMs}`, the longest in all first, then by id.
|
||||
- `console` is `{lines, droppedLines, truncatedLines}`: the run's own output, `vc.log` lines and uncaught error, as
|
||||
text.
|
||||
- `dialogs` lists the run's dialogs in the order they opened, as `{kind, message, title, errorIcon, answer}` for
|
||||
`alert`, `{kind, message, title, noAsDefault, answer}` for `confirm` and `{kind, message, title, preset, answer}`
|
||||
for `prompt`. `answer` is `"ok"`, `true`, `false`, the prompt's text, `null` for Cancel, `"stop"` for a dialog the
|
||||
run ended at, or `"missing"` for a dialog `answers` had no answer for. `dialogCount` counts every dialog, and
|
||||
`dialogsTruncated` is true when the list stopped at its limit.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"script.run","params":{"source":"vc.run('shape.rectangle', {x: 0, y: 0, width: 10, height: 10});"}}}
|
||||
@@ -1660,6 +1669,47 @@ have no prompts yet.
|
||||
vectorcraft-cli run --cmd script.run --params '{"path": "Tidy Layers.js", "args": {"margin": 12}}'
|
||||
```
|
||||
|
||||
The help page https://extendscript.docsforadobe.dev/extendscript-tools-features/user-notification-dialogs/
|
||||
describes the three dialog functions. A script calls them as globals:
|
||||
|
||||
- `alert(message[, title, errorIcon])` shows the message with OK, and an error icon when `errorIcon` is true. It
|
||||
returns `undefined`.
|
||||
- `confirm(message[, noAsDflt, title])` shows the message with Yes and No. Yes is the default button, and No is the
|
||||
default when `noAsDflt` is true. It returns `true` for Yes and `false` for No.
|
||||
- `prompt(message, preset[, title])` shows the message and a text field that starts with `preset`, with OK and
|
||||
Cancel. It returns the field's text for OK, an empty string included, and `null` for Cancel.
|
||||
|
||||
The message, the preset and a given title are read as `String(value)` gives them, and `errorIcon` and `noAsDflt` as
|
||||
`Boolean(value)` gives them. A title that is left out or `undefined` is Script Alert. A call without a message, or a
|
||||
`prompt` without a preset, throws a `TypeError`. A message or a prompt's preset longer than 16 KiB, or a title longer than
|
||||
256 bytes, throws a `RangeError` and opens no dialog. The dialog shows line feeds, carriage returns and the two
|
||||
together as line breaks, and other control characters as their Unicode Control Pictures. The title stays on one
|
||||
line, with line breaks shown as Control Pictures too.
|
||||
|
||||
In the app, the run waits at the call until the person answers, and spends no instructions while it waits. Enter
|
||||
gives the default button's answer. Escape gives Cancel for a prompt, No for a confirm and Stop for an alert. Every
|
||||
dialog also has Stop, which ends the run as `script.stop` does and puts back every document. A dialog can open only
|
||||
from the script's own code: called inside a callback of a built-in function such as `Array.prototype.forEach`, a
|
||||
getter, a `toString` conversion or a file `$.evalFile` runs, it throws an `Error`. The code of an `#include` file
|
||||
is part of the script's own code, and its dialogs open as the script's do. Quitting while a dialog waits asks whether to stop the
|
||||
script, and Cancel shows the dialog again with the text typed so far. In the app, `ui.dialog.confirm` answers the
|
||||
open dialog (kind `scriptDialog`) with its `answer` field (`ok`, `yes`, `no`, `cancel` or `stop`), or with the
|
||||
default button's answer when `answer` is left out. A prompt's `value` longer than 16 KiB is an error, and the
|
||||
dialog stays open.
|
||||
|
||||
A run with nobody to ask takes its answers from `answers`, a list of `{kind: "alert", value: "ok"}`, `{kind:
|
||||
"confirm", value: true}` or `{kind: "confirm", value: false}`, and `{kind: "prompt", value: text}` or `{kind:
|
||||
"prompt", value: null}` for Cancel. Each dialog takes the next answer in order, callbacks of built-in functions
|
||||
included. The run ends with an error that the script cannot catch, and every document goes back, when no answer is
|
||||
left, when the next answer is for another kind of dialog, or when the script ends with answers it did not use.
|
||||
`script.run` refuses a list that is malformed, longer than 10,000 answers or larger than 1 MiB before the run starts,
|
||||
and refuses any answers for a run in the app, where the person answers. An omitted `answers`, an empty list and an
|
||||
empty object are the same.
|
||||
|
||||
```sh
|
||||
vectorcraft-cli run --cmd script.run --params '{"source": "if (confirm(\"Add a frame?\")) vc.log(prompt(\"Name\", \"Frame\"));", "answers": [{"kind": "confirm", "value": true}, {"kind": "prompt", "value": "Border"}]}'
|
||||
```
|
||||
|
||||
Window › Script Console shows the session's script lines, oldest first: each run's start, its `$.write` and
|
||||
`$.writeln` output, its `vc.log` entries, its uncaught error as `name:line:column: message` (or `name: file:line:column: message` when the error is in another
|
||||
file), its end, and a report of
|
||||
|
||||
@@ -731,6 +731,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- Scripts: Window › Script Console shows each run's `$.write` and `$.writeln` output, `vc.log` entries, uncaught error with the script's name, line and column, and a report of its time, host calls and slowest commands, keeping at most 2,048 lines and counting the lines it dropped. `script.run`'s report carries the same data, and `script.console`, `script.console.clear` and `ui.copyScriptConsole` read, clear and copy it. `crates/engine/src/tests/script_console.rs`.
|
||||
- Scripts: a run reads its preprocessor lines before any of it runs: `#include` and `//@include` put another file in place of the line, looked for beside the including file, in the `#includepath` folders and in `JSINCLUDE`; `#script` names the run; `#target` and `#strict off` are taken, and `#strict on`, `#targetengine` and `#engine` are refused. `$.evalFile` runs a file with the same globals and returns its last value, and `$.fileName` and `$.includePath` give the file being run and the include folders. A script run from a file reads these files only in its folder and below, without `..` names or links that lead out, and an error in one is reported at its own file, line and column ([preprocessor directives](https://extendscript.docsforadobe.dev/extendscript-tools-features/preprocessor-directives/), [the `$` object](https://extendscript.docsforadobe.dev/extendscript-tools-features/dollar-object/); `crates/engine/src/tests/script_include.rs`).
|
||||
- Scripts folder: File › Scripts lists the `.js` and `.jsx` files of the `Scripts` folder next to the preferences, each named after its file without the extension, with each subfolder as a submenu, above Check Script… and Other Script… (https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/install-and-run-scripts.html). VectorCraft's own rules: the folder is read again when the window becomes active and when the File menu opens, links are not followed, and one read stops at 2,048 entries, 512 scripts, 128 subfolders, 4 levels or 250 ms. `script.listInstalled` returns the listing. `crates/engine/src/tests/script_folder.rs`, `crates/ui-egui/src/tests/scripts_menu.rs`.
|
||||
- Scripts: `alert`, `confirm` and `prompt` open dialogs during a run, each with a Stop button that ends the run and puts every document back. In the app the run waits at the call for the person's answer; a run over MCP or the command line takes its answers in order from `script.run`'s `answers`, and the report lists each dialog with its answer. `crates/engine/src/tests/script_dialogs.rs`, `crates/ui-egui/src/tests/script_dialogs.rs`.
|
||||
- Parameter keys: the engine refuses a key that a command's params description doesn't name before the command runs, in every build and for every caller, including the app's own calls, the commands a command runs and the steps of `command.batch` and `action.batch`. An action recorded by an older version still plays from the Actions panel and the Batch dialog (`Session::replay`). `crates/engine/tests/it/param_keys.rs`.
|
||||
- MCP server with 25 tools (drawing, text, effects, Pathfinder, transforms, graphs, text wrap, export, screenshots, any command), attached to the running app or headless. Tool descriptions and replies agree with the engine: format lists come from its format table, `save_file` says it keeps the document's own format, `inspect_document` reports the paint type's characters show, and selection exports report the encoder's warnings. `--automation-read-root` / `--automation-write-root` (on `vectorcraft-cli mcp` and on `vectorcraft --control`) confine the files commands read and write to chosen folders, links followed, with the flags PhotoCraft takes (#832); each flag may be given more than once, a path inside any of its folders being allowed (#3546, `file_access::tests::several_roots_of_a_kind_each_grant_their_access`, `cli::mcp_automation_roots_take_several_folders`). A long export can be cancelled (`notifications/cancelled` stops it at the next page or group and writes nothing), reports page progress to a client that sent a progress token, and does not make other requests wait: engine-free ones answer at once, the rest are refused as busy after two seconds (#2165, #2171, #2172).
|
||||
- MCP protocol: five prompts (`prompts/list` / `prompts/get`: poster, icon set, recolour, trace-and-style, export set), `completion/complete` for prompt arguments and template variables read from the live catalogues (formats, effect ids, command ids, trace presets, swatch and object ids), four resource templates (`vectorcraft://object/{id}`, `//command/{id}`, `//effect/{id}`, `//swatch/{name}`) so an agent reads one thing instead of the whole document, and `logging/setLevel` with `notifications/message`. `window.panel` ids are case-insensitive (display labels work too), `vectorcraft://object/{id}` reads through `document.node {summary: true}` (the same reply bytes from one lookup instead of summarizing the whole document: a leaf read on a 2,000-object document drops from ~20 ms to ~0.06 ms), large containers slice with `document.node {depth?, childLimit?}` (truncated levels report `childCount`), `document.inspect` and the `inspect_document` tool slice the same way so a depth-0 read is the layer skeleton (~9.7 KB instead of ~2 MB on a 2,000-object document), `document.find` locates nodes by name/kind/text with ancestor paths, and the CLI sweeps the protocol surface over stdio against the compiled binary. `docs/mcp.md` has a Protocol section covering the capability table and what is deliberately absent (subscriptions, progress, cancellation, sampling, elicitation, Streamable HTTP — all of which need the transport to interleave reads).
|
||||
|
||||
Reference in New Issue
Block a user