@engenty/wizards-runtime 0.7.11 → 0.8.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 (108) hide show
  1. package/README.md +5 -1
  2. package/apps/runtime/dist/authoring/guide.js +14 -2
  3. package/apps/runtime/dist/cli/exec.js +4 -1
  4. package/apps/runtime/dist/connectors/builtin.js +4 -2
  5. package/apps/runtime/dist/connectors/index.js +35 -4
  6. package/apps/runtime/dist/connectors/smtp.js +221 -0
  7. package/apps/runtime/dist/db/migrations/tenant/0018_share_job.sql +18 -0
  8. package/apps/runtime/dist/db/migrations/tenant/meta/0018_snapshot.json +3460 -0
  9. package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +7 -0
  10. package/apps/runtime/dist/db/schema.js +19 -0
  11. package/apps/runtime/dist/docs/dev/index.md +25 -13
  12. package/apps/runtime/dist/docs/dev/meta.json +8 -2
  13. package/apps/runtime/dist/docs/dev/wizard-format/agent-steps.md +112 -0
  14. package/apps/runtime/dist/docs/dev/wizard-format/branches.md +63 -0
  15. package/apps/runtime/dist/docs/dev/wizard-format/film-steps.md +47 -0
  16. package/apps/runtime/dist/docs/dev/wizard-format/generate-steps.md +57 -0
  17. package/apps/runtime/dist/docs/dev/wizard-format/index.md +188 -0
  18. package/apps/runtime/dist/docs/dev/wizard-format/lists-and-connections.md +65 -0
  19. package/apps/runtime/dist/docs/dev/wizard-format/meta.json +19 -0
  20. package/apps/runtime/dist/docs/dev/wizard-format/pages-and-fields.md +102 -0
  21. package/apps/runtime/dist/docs/dev/wizard-format/review-and-result.md +64 -0
  22. package/apps/runtime/dist/docs/dev/wizard-format/templates.md +57 -0
  23. package/apps/runtime/dist/docs/dev/wizard-format/validate.md +63 -0
  24. package/apps/runtime/dist/docs/dev/wizard-format/views-and-widgets.md +103 -0
  25. package/apps/runtime/dist/docs/dev/wizard-format/wizard-file.md +147 -0
  26. package/apps/runtime/dist/docs/user/run.md +21 -4
  27. package/apps/runtime/dist/docs/user/steps.md +26 -1
  28. package/apps/runtime/dist/docs/user/test-and-share.md +3 -2
  29. package/apps/runtime/dist/engine/requirements.js +22 -7
  30. package/apps/runtime/dist/engine/runner.js +17 -8
  31. package/apps/runtime/dist/env.js +5 -0
  32. package/apps/runtime/dist/harness/antigravity.js +2 -10
  33. package/apps/runtime/dist/harness/claude.js +2 -10
  34. package/apps/runtime/dist/harness/codex.js +5 -11
  35. package/apps/runtime/dist/harness/cursor.js +2 -10
  36. package/apps/runtime/dist/harness/env.js +23 -0
  37. package/apps/runtime/dist/harness/index.js +6 -3
  38. package/apps/runtime/dist/routes/runs.js +106 -6
  39. package/apps/runtime/dist/routes/studio.js +12 -0
  40. package/apps/runtime/dist/sharing/agent.js +65 -0
  41. package/apps/runtime/dist/sharing/files.js +121 -0
  42. package/apps/runtime/dist/sharing/index.js +298 -0
  43. package/apps/runtime/dist/sharing/jobs.js +186 -0
  44. package/apps/runtime/dist/sharing/state.js +116 -0
  45. package/apps/runtime/dist/sharing/targets/browser.js +131 -0
  46. package/apps/runtime/dist/sharing/targets/connector.js +63 -0
  47. package/apps/runtime/dist/sharing/targets/email.js +98 -0
  48. package/apps/runtime/dist/sharing/targets/slack.js +54 -0
  49. package/apps/runtime/dist/sharing/targets/storage.js +164 -0
  50. package/apps/runtime/dist/sharing/types.js +13 -0
  51. package/apps/runtime/dist/texts.js +108 -0
  52. package/apps/runtime/dist/tools/browser.js +48 -0
  53. package/apps/runtime/dist/tools/connector.js +3 -2
  54. package/apps/runtime/dist/tools/store.js +18 -1
  55. package/apps/web/dist/assets/AboutDialog-CiiSwL4t.js +1 -0
  56. package/apps/web/dist/assets/{ChangelogDialog-CZrd-MgC.js → ChangelogDialog-BEyz7LNE.js} +1 -1
  57. package/apps/web/dist/assets/ChatView-9RkWts5F.js +10 -0
  58. package/apps/web/dist/assets/EditorPage-CCsKKcYo.js +4 -0
  59. package/apps/web/dist/assets/{FlowPreview-oX_Emm7u.js → FlowPreview-CLf8WHiG.js} +1 -1
  60. package/apps/web/dist/assets/{Harness-DiB8CBdY.js → Harness-jc3jpWvI.js} +2 -2
  61. package/apps/web/dist/assets/NewWizardChannels-BPGZ4pfP.js +1 -0
  62. package/apps/web/dist/assets/NewWizardPage-tidycL7Y.js +7 -0
  63. package/apps/web/dist/assets/OnboardingPage-DtVuaIuv.js +1 -0
  64. package/apps/web/dist/assets/ProjectPage-BsWgCP5z.js +1 -0
  65. package/apps/web/dist/assets/PublicRunner-CkA_etKX.js +1 -0
  66. package/apps/web/dist/assets/{ReadOnly-CD5YWvrW.js → ReadOnly-BVwbqvpi.js} +1 -1
  67. package/apps/web/dist/assets/RunDrawer-CkFpnWCC.js +4 -0
  68. package/apps/web/dist/assets/{RunnerView-BW1h4x63.js → RunnerView-CxTFM-lx.js} +1 -1
  69. package/apps/web/dist/assets/SettingsPage-DM1wNAE7.js +1 -0
  70. package/apps/web/dist/assets/SetupPage-BKnQqiab.js +1 -0
  71. package/apps/web/dist/assets/{SharePage-B6u9kS12.js → SharePage-CTTSudtp.js} +1 -1
  72. package/apps/web/dist/assets/changelog-DBEwyB1f.js +1 -0
  73. package/apps/web/dist/assets/{esm-C-ZWeuhU.js → esm-DtNAg8uF.js} +1 -1
  74. package/apps/web/dist/assets/index-V1M59Yez.css +1 -0
  75. package/apps/web/dist/assets/index-xIz8znhq.js +14 -0
  76. package/apps/web/dist/assets/{oss-credits-Bc05Qv5H.js → oss-credits-BWE03Xax.js} +1 -1
  77. package/apps/web/dist/assets/{phone-BjmhIKuT.js → phone-5SYD9OrJ.js} +1 -1
  78. package/apps/web/dist/assets/{settings-menu-Dpkp3f56.js → settings-menu-Bn5-7Lqk.js} +1 -1
  79. package/apps/web/dist/assets/ui-s39eGOtW.js +137 -0
  80. package/apps/web/dist/assets/{upload-JX9BcMTq.js → upload-Bevcvx5V.js} +1 -1
  81. package/apps/web/dist/assets/{wrench-BSxnPs2_.js → wrench-ZD5SCsz9.js} +1 -1
  82. package/apps/web/dist/index.html +3 -3
  83. package/apps/web/dist/mcp/flow.html +53 -53
  84. package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +22 -0
  85. package/node_modules/@engenty-wizards/shared/dist/definition.js +26 -0
  86. package/node_modules/@engenty-wizards/shared/dist/run.d.ts +6 -0
  87. package/node_modules/@engenty-wizards/shared/dist/run.js +2 -0
  88. package/node_modules/@engenty-wizards/shared/dist/sharing.d.ts +135 -0
  89. package/node_modules/@engenty-wizards/shared/dist/sharing.js +11 -0
  90. package/node_modules/@engenty-wizards/shared/dist/store.d.ts +8 -0
  91. package/package.json +2 -1
  92. package/plugin/.claude-plugin/plugin.json +1 -1
  93. package/apps/runtime/dist/docs/dev/wizard-format.md +0 -125
  94. package/apps/web/dist/assets/AboutDialog-CPRAlD2H.js +0 -1
  95. package/apps/web/dist/assets/ChatView-DVeERQdi.js +0 -10
  96. package/apps/web/dist/assets/EditorPage-DhUoKcss.js +0 -4
  97. package/apps/web/dist/assets/NewWizardChannels-Ba3XGpro.js +0 -1
  98. package/apps/web/dist/assets/NewWizardPage-C2Oh2sMM.js +0 -7
  99. package/apps/web/dist/assets/OnboardingPage-D_4ShWrL.js +0 -1
  100. package/apps/web/dist/assets/ProjectPage-C58rq50b.js +0 -1
  101. package/apps/web/dist/assets/PublicRunner-CE0ohzyd.js +0 -1
  102. package/apps/web/dist/assets/RunDrawer-Cd8-qHV7.js +0 -4
  103. package/apps/web/dist/assets/SettingsPage-ChYLv-MG.js +0 -1
  104. package/apps/web/dist/assets/SetupPage-hX7deF0g.js +0 -1
  105. package/apps/web/dist/assets/changelog-Dn9LT4MS.js +0 -1
  106. package/apps/web/dist/assets/index-4jH2mkp7.js +0 -14
  107. package/apps/web/dist/assets/index-BwW652E-.css +0 -1
  108. package/apps/web/dist/assets/ui-DMmT-cSO.js +0 -137
@@ -0,0 +1,19 @@
1
+ {
2
+ "title": "The wizard format",
3
+ "pages": [
4
+ "index",
5
+ "validate",
6
+ "wizard-file",
7
+ "---Steps---",
8
+ "pages-and-fields",
9
+ "agent-steps",
10
+ "generate-steps",
11
+ "views-and-widgets",
12
+ "film-steps",
13
+ "review-and-result",
14
+ "---Across steps---",
15
+ "templates",
16
+ "branches",
17
+ "lists-and-connections"
18
+ ]
19
+ }
@@ -0,0 +1,102 @@
1
+ ---
2
+ title: Pages and fields
3
+ description: A page step and its fields, the field kinds, and fields that show only when they fit.
4
+ version: 0.7.10
5
+ ---
6
+
7
+ A `page` step asks the person. It holds at least one field, and a good page has at most five.
8
+ `cta` is the button’s label.
9
+
10
+ ```json
11
+ {
12
+ "id": "about", "type": "page", "title": "What is it about?", "cta": "Write it",
13
+ "fields": [
14
+ { "id": "topic", "label": "Topic", "kind": "textarea", "required": true,
15
+ "placeholder": "e.g. We open our new studio on Friday", "help": "For the first line" },
16
+ { "id": "tone", "label": "Tone", "kind": "select",
17
+ "options": ["Casual", "Professional"], "default": "Casual" }
18
+ ]
19
+ }
20
+ ```
21
+
22
+ A field’s `id` is unique in the whole wizard, because later steps read the answer by it. Every
23
+ field has a `label` and a `kind`, and may have `required`, `placeholder`, `help` and `default`.
24
+
25
+ ## Field kinds
26
+
27
+ | Kind | What the person gives | Keys of its own |
28
+ |---|---|---|
29
+ | `text`, `textarea` | A line, or a few paragraphs | `scan` (text): fill it from a QR code or barcode |
30
+ | `number`, `date`, `email`, `url` | A number, a date, an address, a link | |
31
+ | `select`, `multiselect` | One or several of `options` | `optionsFrom`, `cards` |
32
+ | `toggle` | Yes or no | |
33
+ | `color` | A colour | |
34
+ | `image` | Photos, taken or uploaded | `multiple`, `min`, `max` (up to 30) |
35
+ | `file` | Documents, photos, recordings | `multiple`, `min`, `max`, `camera`, `video`, `listen` |
36
+ | `items` | Line items with totals | `columns`, `vat`, `currency` |
37
+ | `location` | Where they are, or an address they type | |
38
+ | `audio` | A voice note of up to 5 minutes, written down before the next step | |
39
+ | `signature` | A signature drawn with the finger | |
40
+ | `slot` | One appointment time, shown by day | `options` or `optionsFrom`, as ISO 8601 date-times |
41
+ | `connection` | Connects one of their accounts | `connection`: the id of a wizard connection |
42
+ | `list` | Checks and corrects a stored list | `list`: the id of a wizard list |
43
+
44
+ ## Line items
45
+
46
+ An `items` field takes positions and computes the totals itself:
47
+
48
+ ```json
49
+ { "id": "positions", "label": "Positions", "kind": "items", "currency": "EUR",
50
+ "vat": { "rate": 20 },
51
+ "columns": [
52
+ { "id": "what", "label": "Service", "kind": "text" },
53
+ { "id": "hours", "label": "Hours", "kind": "number" },
54
+ { "id": "rate", "label": "Rate", "kind": "money" }
55
+ ] }
56
+ ```
57
+
58
+ A row’s amount is the product of its `number` and `money` columns. `vat.field` reads the rate
59
+ from another field instead. Documents take the table with its totals from `{{positions}}`. See
60
+ [Templates](./templates.md).
61
+
62
+ ## Answers from earlier steps
63
+
64
+ - `prefill` (`"steps.<id>.<key>"`): what the field starts with. An `items` field takes a table
65
+ whose columns are its column ids, and the person corrects the rows.
66
+ - `optionsFrom`: the choices of a `select`, `multiselect` or `slot` come from earlier data. It
67
+ names a list output (`steps.<id>.<key>`), a column of a table output
68
+ (`steps.<id>.<key>.<column>`) or a column of a stored list (`lists.<id>.<column>`). `options`
69
+ stand in while that data is empty.
70
+ - `cards`: with `optionsFrom` naming a table output, each row is a card. Its keys name the
71
+ table’s columns: `label`, `value` (default: the label), `image`, `subtitle`, `meta` and `link`.
72
+
73
+ ## Fields that show only when they fit
74
+
75
+ `when` shows a field only while a condition holds. It reads a field of the same page, decided as
76
+ the person types, or anything known before the page:
77
+
78
+ ```json
79
+ { "id": "company", "label": "Company", "kind": "text",
80
+ "when": { "field": "customerType", "op": "equals", "value": "Business" } }
81
+ ```
82
+
83
+ A hidden field is not asked and not kept. Its template is empty. Conditions are described on
84
+ [Branches and loops](./branches.md#conditions).
85
+
86
+ Where no rule on one field can say it, a decision picks the fields as the run reaches the page:
87
+
88
+ - `ask` on a field: a statement. The field shows when the decision finds it true of the run,
89
+ for example “The complaint is about a damaged article”.
90
+ - `groups` on the page and `group` on fields: of a group’s fields the decision shows one. With
91
+ `optional`, it may show none.
92
+
93
+ ```json
94
+ "groups": [{ "id": "reach", "instructions": "How should we reach the person?" }],
95
+ "fields": [
96
+ { "id": "phone", "label": "Phone", "kind": "text", "group": "reach" },
97
+ { "id": "mail", "label": "Email", "kind": "email", "group": "reach" }
98
+ ]
99
+ ```
100
+
101
+ A page with decided fields holds up to 12 fields and shows at most 5. A field has `ask` or
102
+ `group`, not both.
@@ -0,0 +1,64 @@
1
+ ---
2
+ title: Review and result
3
+ description: A review step shows earlier results to check, the result step ends the run with its downloads.
4
+ version: 0.7.10
5
+ ---
6
+
7
+ ## Review
8
+
9
+ A `review` step shows what earlier steps made. The person accepts it, changes it or asks for a
10
+ new version.
11
+
12
+ ```json
13
+ {
14
+ "id": "check", "type": "review", "title": "Does this work?",
15
+ "show": ["post", "visual"], "edit": true, "regenerate": true
16
+ }
17
+ ```
18
+
19
+ | Key | What it does |
20
+ |---|---|
21
+ | `show` | The step ids whose results are shown, or `lists.<id>` for a stored list |
22
+ | `edit` | The person may change text results directly |
23
+ | `regenerate` | The person may ask for a new version, with a note |
24
+
25
+ A shown list is edited in place. A list with `check` goes row by row on a split screen. See
26
+ [Lists and connections](./lists-and-connections.md#lists).
27
+
28
+ Put a review before anything expensive, such as video, and before anything written elsewhere,
29
+ such as a mail or a CRM.
30
+
31
+ ## Result
32
+
33
+ The `result` step is always the last. It shows `message` and offers the downloads.
34
+
35
+ ```json
36
+ {
37
+ "id": "done", "type": "result", "title": "Ready to post",
38
+ "message": "Copy the text and download the image.",
39
+ "deliverables": [
40
+ { "from": "post", "label": "Post", "formats": ["txt", "md"] },
41
+ { "from": "visual", "label": "Image", "formats": ["png"] }
42
+ ]
43
+ }
44
+ ```
45
+
46
+ Each deliverable names a step id or `lists.<id>` in `from`, an optional `label` and its
47
+ `formats`.
48
+
49
+ ## Formats
50
+
51
+ | From | Formats |
52
+ |---|---|
53
+ | `generate` image | `png` |
54
+ | `generate` video | `mp4`, `zip` for several results |
55
+ | `generate` voice | `mp3` |
56
+ | `generate` document | `pdf`, `docx`, `html`, `md`, `png` |
57
+ | `generate` dashboard | `html`, `pdf`, `png` |
58
+ | `widget` | `html`, `png`, `pdf`, `json`, and `mp4` when the widget has a timeline |
59
+ | `widget` with `video` | `mp4`, `png` |
60
+ | `film` | `mp4` |
61
+ | `agent` with `text` or `markdown` | `md`, `txt`, `docx`, `pdf`, `html` |
62
+ | `agent` with `json` | `json`, `csv`, `xlsx` (a sheet per table), `md`, and `pdf` with a `schema` |
63
+ | `agent`, any format | `zip`: the files the step kept |
64
+ | `lists.<id>` | `xlsx`, `csv`, `json`, `md`, and `zip` for a list with `check.file` |
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: Templates
3
+ description: How instructions, prompts and briefs read answers, earlier results, the space and stored lists.
4
+ version: 0.7.10
5
+ ---
6
+
7
+ Instructions, prompts and briefs are templates. `{{…}}` is filled in when the step runs:
8
+
9
+ ```text
10
+ Write a post for X on {{topic}}. Tone: {{tone}}. Use these facts: {{steps.research}}
11
+ ```
12
+
13
+ A template may only name fields asked and steps run earlier. `wizards validate` says when one
14
+ does not.
15
+
16
+ ## What a template reads
17
+
18
+ | Template | What it gives |
19
+ |---|---|
20
+ | `{{fieldId}}` | The answer to a field |
21
+ | `{{steps.stepId}}` | A step’s whole result |
22
+ | `{{steps.stepId.key}}` | One key of a `json` step’s result |
23
+ | `{{lists.listId}}` | A stored list as a table, as it is when the step starts |
24
+ | `{{today}}` | Today’s date |
25
+ | `{{brand.name}}`, `{{brand.about}}`, `{{brand.colors}}` | The space’s brand |
26
+ | `{{facts.key}}`, `{{facts}}` | One fact of the space, such as its address or VAT ID, or all of them |
27
+
28
+ Every AI step already knows the brand and the facts. Name one only where the text must carry it.
29
+
30
+ ## Fields with more than one value
31
+
32
+ | Template | What it gives |
33
+ |---|---|
34
+ | `{{itemsField}}` | The line items as a table with net, VAT and total |
35
+ | `{{itemsField.net}}`, `.vat`, `.gross` | One of the totals |
36
+ | `{{fileField}}` | The names of the uploads |
37
+ | `{{field.speech}}` | A `file` field with `listen`: what is said, piece by piece with times |
38
+ | `{{audioField}}`, `{{audioField.seconds}}` | What the person said, and how long |
39
+ | `{{locationField}}` | The address with its position, for example “Herrengasse 16, Graz (47.07071, 15.43950, ±12 m)” |
40
+ | `.lat`, `.lng`, `.accuracy`, `.label`, `.map` | One part of a location, `.map` a map link |
41
+ | `{{signatureField}}` | The picture as `asset://ID`, for `<img src="asset://ID">` in a document |
42
+
43
+ Documents take `{{itemsField}}` as it is. The runner computes the totals, never a model.
44
+
45
+ ## Inside a step with `each`
46
+
47
+ | Template | What it gives |
48
+ |---|---|
49
+ | `{{item.column}}` | One column of the current entry |
50
+ | `{{index}}` | The number of the entry |
51
+ | `{{count}}` | How many entries there are |
52
+
53
+ ## References outside templates
54
+
55
+ Other keys name the same things without braces: `prefill`, `optionsFrom`, `each`, a widget’s or
56
+ surface’s `data` and a condition’s `field`. They take `fieldId`, `steps.<id>`, `steps.<id>.<key>`
57
+ and `lists.<id>`, as each key’s page says.
@@ -0,0 +1,63 @@
1
+ ---
2
+ title: JSON Schema and validation
3
+ description: The JSON Schema for your editor, and wizards validate for everything a schema cannot say.
4
+ version: 0.7.10
5
+ ---
6
+
7
+ ## JSON Schema
8
+
9
+ | For | Schema |
10
+ |---|---|
11
+ | A definition | [`https://engenty.ai/schema/v1/wizard.json`](https://engenty.ai/schema/v1/wizard.json) |
12
+ | `wizard.json` in a package | [`https://engenty.ai/schema/v1/wizard-package.json`](https://engenty.ai/schema/v1/wizard-package.json) |
13
+
14
+ Put the address under `"$schema"`, and editors such as VS Code complete keys and mark mistakes
15
+ as you type. The studio’s export writes it into every `wizard.json`.
16
+
17
+ The schemas are written from the code that reads wizards, so they match it. They are stricter
18
+ in one way: a key the app does not know is an error. The app would drop such a key without a
19
+ word.
20
+
21
+ ## `wizards validate`
22
+
23
+ ```bash
24
+ wizards validate invoice.wizard
25
+ ```
26
+
27
+ It checks a wizard the way the studio’s import does, without a running studio and without an
28
+ account. It also checks what a JSON Schema cannot say: unique ids, steps and fields that refer
29
+ to each other, templates that name answers that exist by then, and files in the workspace.
30
+
31
+ It takes any number of paths:
32
+
33
+ | Path | Read as |
34
+ |---|---|
35
+ | `invoice.wizard` | A package |
36
+ | `invoice/` or `invoice/wizard.json` | An unpacked package, its workspace under `invoice/files/` |
37
+ | `invoice.json` | A definition on its own, or a `wizard.json` |
38
+
39
+ ```text
40
+ ✗ invoice.json 2 issues
41
+ The last step must be a result step.
42
+ "{{nope}}" refers to a field that is not asked before "g".
43
+ ```
44
+
45
+ A wizard without issues gets a ✓ with its number of steps and files. `--json` prints the
46
+ results as JSON. The exit code is `0` when every wizard is fine, `1` when one has issues and `2`
47
+ when no path was given.
48
+
49
+ ## In CI
50
+
51
+ ```bash
52
+ npx wizards validate wizards/*.wizard
53
+ ```
54
+
55
+ `npx wizards` installs engenty wizards into `~/.engenty/wizards` first, the first time. To check
56
+ without an install, on Node.js 24.11 or newer, run the runtime from npm directly:
57
+
58
+ ```bash
59
+ npx -p @engenty/wizards-runtime wizards validate wizards/*.wizard
60
+ ```
61
+
62
+ What belongs to a space is checked only on import. See
63
+ [What the import takes](./wizard-file.md#what-the-import-takes).
@@ -0,0 +1,103 @@
1
+ ---
2
+ title: Views and widgets
3
+ description: Surfaces built from the catalog, a view of an agent step's result, nested output, and HTML widgets.
4
+ version: 0.7.10
5
+ ---
6
+
7
+ A result can show as a view instead of a plain table. There are three ways:
8
+
9
+ | Way | What it is | Costs per run |
10
+ |---|---|---|
11
+ | A `surface` step | A view built from the surface catalog, written once | Nothing |
12
+ | `output.surface` on an agent step | The same, bound to that step’s own result | Nothing |
13
+ | A `widget` step | An HTML app in the wizard’s workspace, written once | Nothing |
14
+
15
+ Choose a surface for facts, a list of results, key figures or a chart. Choose a widget for what
16
+ the catalog cannot show, such as a map or an animation.
17
+
18
+ ## Surfaces
19
+
20
+ A surface is a flat array of components. The one with id `root` is drawn, and containers list
21
+ their children by id. A prop is a value, or `{ "path": "/key/…" }` into the data.
22
+
23
+ ```json
24
+ {
25
+ "id": "show", "type": "surface", "title": "Your offers",
26
+ "data": { "offers": "steps.research.offers" },
27
+ "components": [
28
+ { "id": "root", "component": "Column", "children": ["head", "list"] },
29
+ { "id": "head", "component": "Text", "text": "Three offers for you", "variant": "lead" },
30
+ { "id": "list", "component": "List", "children": { "path": "/offers", "componentId": "row" } },
31
+ { "id": "row", "component": "Row", "title": { "path": "name" }, "meta": { "path": "price" } }
32
+ ]
33
+ }
34
+ ```
35
+
36
+ `data` maps keys to what the surface reads: a field id, `steps.<id>`, `steps.<id>.<key>`,
37
+ `lists.<id>`, `brand.name` or `today`.
38
+
39
+ | Components | For |
40
+ |---|---|
41
+ | `Column`, `Grid`, `Tabs`, `Fold`, `Group` | Layout: stacks, tiles, two to four views, details on a tap, entries under a heading per value |
42
+ | `Text`, `Callout`, `Badge`, `DetailGrid`, `Metric` | Words, a tip or warning, a label, facts, a key figure |
43
+ | `Card`, `List`, `Row`, `Link` | Things: one card per thing, rows, an entry that opens in a sheet |
44
+ | `Chips`, `Checklist`, `Steps` | Short things, things to get or do, ordered work |
45
+ | `Table`, `BarChart`, `LineChart`, `DonutChart` | Figures compared across columns, charts |
46
+ | `Image`, `Actions`, `Button` | A picture, buttons that make the result again or open it |
47
+
48
+ `candidates` replaces `components` when the view should change per run. Each candidate is a piece
49
+ with a `description`, and a decision picks the pieces that fit: no chart when there is nothing to
50
+ chart. `group` and `groups` work as on [pages](./pages-and-fields.md#fields-that-show-only-when-they-fit),
51
+ and `required` pieces always show.
52
+
53
+ The MCP tool `get_authoring_guide` lists every component with its props.
54
+
55
+ ## A view of an agent step’s result
56
+
57
+ An agent step with `output.format` `json` can carry its own view in `output.surface`, bound to
58
+ its keys by path. Reviews and the result show it in place of a table. `output.surface: true` has
59
+ a model compose a view on every run instead, which costs a model call.
60
+
61
+ For nested data, `output.schema` replaces `output.fields`. Its root is an object:
62
+
63
+ ```json
64
+ "schema": { "kind": "object", "label": "Menu plan", "fields": {
65
+ "days": { "kind": "list", "label": "Days", "of": { "kind": "object", "label": "Day", "fields": {
66
+ "label": { "kind": "text", "label": "Day" },
67
+ "recipe": { "kind": "ref", "label": "Recipe", "to": "recipes" } } } },
68
+ "recipes": { "kind": "list", "label": "Recipes", "of": { "kind": "object", "label": "Recipe", "fields": {
69
+ "id": { "kind": "text", "label": "ID" },
70
+ "minutes": { "kind": "number", "label": "Time", "unit": "min" } } } } } }
71
+ ```
72
+
73
+ Kinds are `text` (with `long` for paragraphs), `number` (with `unit`), `yesno` (with `yes` and
74
+ `no`, the words people read), `choice`, `ref` (the id of an entry of a top-level list) and `list`.
75
+ Objects nest at most four deep, with a hundred keys in all. Labels are in the wizard’s language.
76
+ The view is checked against the schema.
77
+
78
+ ## Widgets
79
+
80
+ A `widget` step shows an HTML page from the wizard’s workspace. It is written once, and every run
81
+ only brings new data.
82
+
83
+ ```json
84
+ {
85
+ "id": "map", "type": "widget", "title": "The route",
86
+ "entry": "route/index.html", "sample": "route/sample.json",
87
+ "data": { "stops": "steps.plan.stops" },
88
+ "size": { "width": 1280, "height": 720 }
89
+ }
90
+ ```
91
+
92
+ | Key | What it does |
93
+ |---|---|
94
+ | `entry` | The workspace path of the HTML |
95
+ | `data` | What the page gets as `wizard.data`: key → a field id, `steps.<id>`, `steps.<id>.<key>`, `brand.name` or `today` |
96
+ | `sample` | Example data in the same shape, for previews before any run |
97
+ | `layout` | `fixed` (the default): drawn at `size` and scaled to the page. `page`: part of the page, as tall as its content |
98
+ | `size` | The design size, 200 to 3840 px. The default is 1280 × 720. PNG, PDF and MP4 render at it |
99
+ | `video` | The result is a film: the timeline is rendered to an MP4 with sound |
100
+
101
+ The page loads nothing from the network when it runs. Libraries and reference data are files in
102
+ the workspace. It talks to the runner through `window.wizard`: `data`, `brand`, `ready()`,
103
+ `timeline()`, `state` and `save()`, among others.
@@ -0,0 +1,147 @@
1
+ ---
2
+ title: The .wizard file
3
+ description: The zip a wizard travels in, its folders and manifest, how to make one by hand, and what the import does with it.
4
+ version: 0.7.10
5
+ ---
6
+
7
+ A `.wizard` file is a zip with the wizard’s definition and its workspace. The studio exports
8
+ one, imports one back, and `wizards validate` checks one. Its media type is
9
+ `application/vnd.engenty.wizard+zip`. The file is named after the wizard’s title, such as
10
+ `create-an-invoice.wizard`.
11
+
12
+ ## What is in the zip
13
+
14
+ ```text
15
+ create-an-invoice.wizard
16
+ ├── wizard.json the manifest, with the definition in it
17
+ └── files/ the wizard's workspace
18
+ ├── invoice/
19
+ │ ├── index.html a widget step's entry
20
+ │ ├── app.js
21
+ │ └── sample.json its example data
22
+ ├── lib/
23
+ │ └── chart.min.js libraries the widgets load
24
+ ├── prices.csv reference data AI steps read
25
+ ├── kits/explainer.zip a film step's style kit
26
+ ├── skills/brand/SKILL.md a skill package a film step reads
27
+ └── knowledge/ only in a website package
28
+ └── services/pricing.md
29
+ ```
30
+
31
+ | Path | What it holds |
32
+ |---|---|
33
+ | `wizard.json` | The manifest. See [The manifest](#the-manifest) |
34
+ | `files/` | The workspace: every file the wizard’s steps name by path |
35
+ | `files/knowledge/` | The space’s Knowledge pages, only when the export was asked for them. See [Knowledge](#knowledge) |
36
+
37
+ Only `wizard.json` is required. A wizard without widgets, kits or files has an empty `files/`
38
+ or none.
39
+
40
+ ## The workspace
41
+
42
+ The paths under `files/` are the paths the definition uses. A widget step with
43
+ `"entry": "invoice/index.html"` reads `files/invoice/index.html`, and a film step with
44
+ `"kit": "kits/explainer.zip"` reads `files/kits/explainer.zip`. Apart from `knowledge/`, no
45
+ folder has a fixed meaning. The ones above are what the studio and its assistant write.
46
+
47
+ | Limit | Value |
48
+ |---|---|
49
+ | Files | 200 |
50
+ | One file | 5 MB |
51
+ | All files | 25 MB |
52
+ | The whole zip | 30 MB, with room for the manifest |
53
+ | A path | 200 characters: letters, digits, `_`, `-` and `.`, with `/` between folders |
54
+
55
+ A path starts with a letter, a digit, `_` or `-`. So hidden files such as `.env` and paths with
56
+ `..` are not allowed. The import refuses a file that breaks a limit, and names it.
57
+
58
+ ## The manifest
59
+
60
+ ```json
61
+ {
62
+ "$schema": "https://engenty.ai/schema/v1/wizard-package.json",
63
+ "format": "engenty-wizard",
64
+ "version": 1,
65
+ "exportedAt": "2026-10-18T09:12:00.000Z",
66
+ "definition": { "version": 1, "title": "Create an invoice", "steps": [ … ] },
67
+ "connectors": [
68
+ { "id": "billomat", "name": "Billomat", "domain": "billomat.com", "sourceKind": "openapi" }
69
+ ],
70
+ "mcpServers": [{ "id": "notion", "name": "Notion" }],
71
+ "knowledge": { "pages": 12, "truncated": false }
72
+ }
73
+ ```
74
+
75
+ | Key | What it holds |
76
+ |---|---|
77
+ | `$schema` | The JSON Schema for editors. The app does not read it |
78
+ | `format` | Always `engenty-wizard`. It tells a manifest from a bare definition |
79
+ | `version` | The manifest’s version, `1` |
80
+ | `exportedAt` | When the file was made |
81
+ | `definition` | The wizard. See [The wizard format](./index.md) |
82
+ | `connectors` | Imported connectors the wizard’s connections name: `id`, `name`, `domain` and `sourceKind` (`openapi` or `mcp`), at most 50 |
83
+ | `mcpServers` | The space’s connected systems its agent steps name: `id` and `name`, at most 10 |
84
+ | `knowledge` | Only with Knowledge: how many pages, and whether the cap left some out |
85
+
86
+ `connectors` and `mcpServers` hold names, never addresses, headers or credentials. They let the
87
+ import tell you what the space you import into still needs.
88
+
89
+ ## Knowledge
90
+
91
+ A website runs a wizard without its space. For that, the share dialog’s website package has
92
+ “Take the knowledge along”. The space’s Knowledge pages then come along as Markdown, one file per
93
+ page, at their path under `files/knowledge/`:
94
+
95
+ ```markdown
96
+ ---
97
+ title: "Pricing"
98
+ path: pages/services/pricing
99
+ ---
100
+
101
+ Our hourly rate is …
102
+ ```
103
+
104
+ A page is cut after 60,000 characters. The pages stop at about 2 MB in all, and `truncated` in the
105
+ manifest then says so.
106
+
107
+ ## What stays out
108
+
109
+ A `.wizard` file holds the wizard, not what it collected or what the space owns:
110
+
111
+ - runs, results and uploads
112
+ - the rows of its lists and the accounts people connected
113
+ - the space’s brand, facts and Knowledge, unless Knowledge was asked for
114
+ - the addresses and credentials of connectors and connected systems
115
+ - translations and the wizard’s published versions
116
+
117
+ The studio’s export holds the draft. The website package and the export over the API hold the
118
+ published version.
119
+
120
+ ## Making one by hand
121
+
122
+ Zip a folder that holds `wizard.json` and `files/`:
123
+
124
+ ```bash
125
+ cd create-an-invoice && zip -r ../create-an-invoice.wizard wizard.json files
126
+ ```
127
+
128
+ The zip may also hold that folder itself, as a zip made in the Finder does. The import takes the
129
+ `wizard.json` closest to the top, and the `files/` beside it. It leaves out folders, `__MACOSX/`
130
+ and `.DS_Store`.
131
+
132
+ `wizards validate` reads the unpacked folder as it is, without zipping it. See
133
+ [JSON Schema and validation](./validate.md).
134
+
135
+ ## What the import does
136
+
137
+ The import takes a `.wizard` file, a `wizard.json` on its own, or a definition on its own. A JSON
138
+ file without `"format": "engenty-wizard"` is read as a definition.
139
+
140
+ 1. It checks the zip against the limits before it unpacks anything.
141
+ 2. It checks the definition and that every path it names is in the workspace.
142
+ 3. It makes a new wizard in the space: a draft, not published, with the workspace’s files.
143
+ 4. It tells you which connectors and connected systems the space still lacks.
144
+
145
+ What belongs to the space is checked only here, because only the space has it: its connectors
146
+ and their actions, its connected systems and its plugins’ tools. A manifest of a newer version
147
+ is refused, with a note that the file comes from a newer version of engenty wizards.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Run a wizard
3
3
  description: What you see when you open a wizard's link, on a computer or a phone.
4
- version: 0.5.0
4
+ version: 0.7.11
5
5
  ---
6
6
 
7
7
  ## From the link to the result
@@ -90,9 +90,26 @@ everything” deletes it. Anything nobody used for 400 days is deleted by itself
90
90
 
91
91
  ## Share a result
92
92
 
93
- “Share” on the result page makes a link to the result. You can copy it, send it by email or hand
94
- it to another app. When you ran the wizard over its link, the result and its link are kept for 7
95
- days. “Withdraw link” ends the link earlier.
93
+ “Share” on the result page opens the ways to pass the result on. “Link” makes a link to the
94
+ result: copy it, send it by email or hand it to another app. When you ran the wizard over its
95
+ link, the result and its link are kept for 7 days. “Withdraw link” ends the link earlier.
96
+
97
+ The other tiles send or publish the result itself. Each one walks you through its steps: the
98
+ account it sends with (“Account”), what goes along and where it goes (“What & where”), then
99
+ “Send”. What happens shows in the same window, and “Recent” lists what was sent before. An
100
+ account you connect is kept for your next run, encrypted. “What this wizard remembers” lists it.
101
+
102
+ | Tile | Does | Needs |
103
+ |---|---|---|
104
+ | “Email” | Sends the files you pick as attachments to one or more addresses | Your mailbox: Gmail, Outlook or any mailbox over SMTP. Where the server sends from an address of its own, no account |
105
+ | Google Drive, OneDrive, S3 | Saves the files into a folder, which is created if it doesn’t exist yet | The account |
106
+ | “Slack” | Posts your message with the link to the result in a channel | Your Slack account |
107
+ | A connected service | An AI agent does what you describe in the service, with its actions, and asks before every change | The account, and a few minutes |
108
+ | “Website” | The wizard opens the site in its browser, and an AI agent posts there what you describe. You sign in yourself, and it asks for your leave before anything goes public | A few minutes. LinkedIn, X, Facebook, Instagram and Meta Ads are ready as presets |
109
+
110
+ Which tiles a result offers is the wizard’s choice, see [The result](./steps.md#the-result).
111
+ Without one, every tile that needs no AI agent is there for everyone with the link. The agent
112
+ tiles are there for the wizard’s owner in the studio, as they spend the wizard’s credits.
96
113
 
97
114
  Media made by a model carries an “AI-generated” label. Whoever publishes it has to label it as
98
115
  AI-generated. The file already carries the marking.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Steps
3
3
  description: What a wizard is made of – pages, AI steps, generated media, widgets, reviews and the result.
4
- version: 0.5.0
4
+ version: 0.7.11
5
5
  ---
6
6
 
7
7
  A wizard runs its steps from top to bottom. The last step is always the result.
@@ -179,6 +179,31 @@ Each entry of the result page names a step and the formats the person can downlo
179
179
  | AI step, collected files | ZIP |
180
180
  | List | Excel, CSV, JSON, Markdown; ZIP with the files its rows name |
181
181
 
182
+ Under “Send & publish” the step says where a person can send or publish the result with one
183
+ button, besides the link and the downloads (see [Share a result](./run.md#share-a-result)). Each
184
+ target is a row with a switch and its state: “Ready”, “AI agent · only you”, or “Not set up”.
185
+ A sentence above the rows says what visitors get and what only you get.
186
+
187
+ | Label | Means |
188
+ |---|---|
189
+ | “Default” | Every target that is set up and needs no AI agent. Targets with an agent only you get |
190
+ | “Own list” | You switched a target off, prefilled one or added one: only the targets switched on, in this order. An agent target then runs for everyone with the link, on your credits |
191
+ | “Off” | Every target switched off: the result has only the link and the downloads |
192
+
193
+ “Reset” brings the default back. Targets that are not set up on this server are listed under
194
+ “not set up”, with “Set up” to the connectors.
195
+
196
+ The arrow on a row opens its form: the name on the result page and what each field starts with.
197
+ “Insert” puts a placeholder where the cursor is: an answer, a written result or the brand name.
198
+ In the wizard file they read `{{email}}`, `{{steps.offer}}` and `{{brand.name}}`.
199
+
200
+ While the result step is chosen, the studio shows its result page beside the flow, filled from
201
+ the last test run. “Visitor” and “You” switch between what each of them gets. A target opens to
202
+ its form as the visitor sees it, with the test run’s answers in it; nothing is sent from there.
203
+ On a tablet or a phone, “Result page” switches the view, and “See the result page” opens it from
204
+ the step. The result node on the flow shows the targets too: filled for visitors, a ring for
205
+ you only.
206
+
182
207
  ## Branches
183
208
 
184
209
  A step can send the run somewhere else when a condition holds: a field is or is not a value, is
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Test and share
3
3
  description: Try the wizard, publish it, and hand out its link or put it on a website.
4
- version: 0.5.0
4
+ version: 0.7.11
5
5
  ---
6
6
 
7
7
  ## Test
@@ -216,7 +216,8 @@ On WordPress the plugin writes this code for you, and its results show the page:
216
216
 
217
217
  On the result page, a person can share what they got as a link. The result of a run over the
218
218
  wizard’s link, and the link to it, are deleted after 7 days. The person can withdraw the link
219
- earlier.
219
+ earlier. “Share” also sends the result on – by email, into a cloud folder, to Slack or onto a
220
+ website: see [Share a result](./run.md#share-a-result).
220
221
 
221
222
  ## Move a wizard
222
223