wizards 0.5.0 → 0.5.1
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.md +45 -42
- package/apps/runtime/dist/agents/studio-assistant.js +3 -3
- package/apps/runtime/dist/app.js +7 -4
- package/apps/runtime/dist/auth/index.js +2 -2
- package/apps/runtime/dist/authoring/guide.js +1 -1
- package/apps/runtime/dist/cli/account.js +31 -28
- package/apps/runtime/dist/cli/autostart.js +5 -3
- package/apps/runtime/dist/cli/clients.js +1 -1
- package/apps/runtime/dist/cli/connect.js +24 -24
- package/apps/runtime/dist/cli/features.js +6 -6
- package/apps/runtime/dist/cli/main.js +51 -39
- package/apps/runtime/dist/cli/mcp.js +5 -4
- package/apps/runtime/dist/cli/menu.js +32 -30
- package/apps/runtime/dist/cli/report.js +7 -9
- package/apps/runtime/dist/cli/setup.js +42 -38
- package/apps/runtime/dist/cli/start.js +16 -15
- package/apps/runtime/dist/cli/status.js +20 -20
- package/apps/runtime/dist/cli/ui.js +9 -2
- package/apps/runtime/dist/cli/update.js +6 -6
- package/apps/runtime/dist/cli/validate.js +1 -1
- package/apps/runtime/dist/connectors/external.js +3 -2
- package/apps/runtime/dist/connectors/index.js +5 -5
- package/apps/runtime/dist/connectors/plugin-connections.js +2 -2
- package/apps/runtime/dist/connectors/via-account.js +5 -5
- package/apps/runtime/dist/db/control-schema.js +14 -0
- package/apps/runtime/dist/db/migrations/control/0009_plugin_claim.sql +9 -0
- package/apps/runtime/dist/db/migrations/control/meta/0009_snapshot.json +561 -0
- package/apps/runtime/dist/db/migrations/control/meta/_journal.json +7 -0
- package/apps/runtime/dist/docs/dev/index.md +16 -14
- package/apps/runtime/dist/docs/dev/plugins/connections.md +27 -24
- package/apps/runtime/dist/docs/dev/plugins/events.md +19 -17
- package/apps/runtime/dist/docs/dev/plugins/examples.md +13 -12
- package/apps/runtime/dist/docs/dev/plugins/index.md +29 -24
- package/apps/runtime/dist/docs/dev/plugins/layout.md +20 -19
- package/apps/runtime/dist/docs/dev/plugins/quick-start.md +16 -15
- package/apps/runtime/dist/docs/dev/plugins/reference.md +52 -40
- package/apps/runtime/dist/docs/dev/plugins/reloading.md +24 -23
- package/apps/runtime/dist/docs/dev/plugins/routes.md +26 -22
- package/apps/runtime/dist/docs/dev/plugins/runners.md +49 -44
- package/apps/runtime/dist/docs/dev/plugins/server.md +95 -43
- package/apps/runtime/dist/docs/dev/plugins/shipping.md +19 -16
- package/apps/runtime/dist/docs/dev/plugins/space.md +75 -69
- package/apps/runtime/dist/docs/dev/plugins/starters.md +22 -17
- package/apps/runtime/dist/docs/dev/plugins/studio.md +80 -37
- package/apps/runtime/dist/docs/dev/plugins/styling.md +44 -41
- package/apps/runtime/dist/docs/dev/plugins/tables.md +11 -11
- package/apps/runtime/dist/docs/dev/plugins/tools.md +26 -25
- package/apps/runtime/dist/docs/dev/wizard-format.md +35 -23
- package/apps/runtime/dist/docs/user/ai-apps.md +46 -43
- package/apps/runtime/dist/docs/user/assistant.md +41 -36
- package/apps/runtime/dist/docs/user/build-a-wizard.md +64 -39
- package/apps/runtime/dist/docs/user/command-line.md +47 -44
- package/apps/runtime/dist/docs/user/connectors.md +40 -35
- package/apps/runtime/dist/docs/user/create-account.md +27 -22
- package/apps/runtime/dist/docs/user/data.md +29 -29
- package/apps/runtime/dist/docs/user/first-start.md +26 -28
- package/apps/runtime/dist/docs/user/index.md +16 -17
- package/apps/runtime/dist/docs/user/install.md +28 -27
- package/apps/runtime/dist/docs/user/local-only.md +21 -17
- package/apps/runtime/dist/docs/user/models.md +92 -84
- package/apps/runtime/dist/docs/user/plugins.md +28 -23
- package/apps/runtime/dist/docs/user/run.md +51 -50
- package/apps/runtime/dist/docs/user/server.md +9 -9
- package/apps/runtime/dist/docs/user/space.md +87 -65
- package/apps/runtime/dist/docs/user/steps.md +73 -69
- package/apps/runtime/dist/docs/user/test-and-share.md +127 -105
- package/apps/runtime/dist/docs/user/troubleshooting.md +40 -38
- package/apps/runtime/dist/docs/user/wordpress.md +62 -54
- package/apps/runtime/dist/documents/parse.js +2 -2
- package/apps/runtime/dist/engenty/shims/web-ingest.js +17 -1
- package/apps/runtime/dist/engine/input.js +4 -4
- package/apps/runtime/dist/engine/push.js +2 -2
- package/apps/runtime/dist/engine/runner.js +8 -8
- package/apps/runtime/dist/engine/steps.js +2 -2
- package/apps/runtime/dist/engine/surface.js +1 -1
- package/apps/runtime/dist/film/step.js +3 -3
- package/apps/runtime/dist/harness/claude.js +1 -1
- package/apps/runtime/dist/harness/codex.js +1 -1
- package/apps/runtime/dist/harness/model.js +2 -2
- package/apps/runtime/dist/harness/terminal.js +3 -3
- package/apps/runtime/dist/mcp/handler.js +2 -2
- package/apps/runtime/dist/mcp/tools.js +9 -9
- package/apps/runtime/dist/models.js +15 -15
- package/apps/runtime/dist/plugins/claims.js +56 -0
- package/apps/runtime/dist/plugins/loader.js +2 -0
- package/apps/runtime/dist/plugins/public.js +2 -3
- package/apps/runtime/dist/plugins/runs.js +13 -8
- package/apps/runtime/dist/render/chromium.js +24 -11
- package/apps/runtime/dist/routes/api.js +15 -9
- package/apps/runtime/dist/routes/debug.js +1 -1
- package/apps/runtime/dist/routes/delivery.js +46 -0
- package/apps/runtime/dist/routes/lang.js +7 -0
- package/apps/runtime/dist/routes/marketplace.js +2 -1
- package/apps/runtime/dist/routes/plugin-public.js +2 -1
- package/apps/runtime/dist/routes/plugins.js +13 -14
- package/apps/runtime/dist/routes/runs.js +59 -49
- package/apps/runtime/dist/routes/studio.js +53 -23
- package/apps/runtime/dist/services/access.js +3 -3
- package/apps/runtime/dist/services/assistant-chats.js +1 -1
- package/apps/runtime/dist/services/brand.js +2 -2
- package/apps/runtime/dist/services/cloud.js +5 -4
- package/apps/runtime/dist/services/errors.js +2 -1
- package/apps/runtime/dist/services/knowledge-model.js +2 -2
- package/apps/runtime/dist/services/marketplace.js +2 -2
- package/apps/runtime/dist/services/package-file.js +12 -9
- package/apps/runtime/dist/services/package.js +2 -2
- package/apps/runtime/dist/services/project-files.js +10 -12
- package/apps/runtime/dist/services/projects.js +13 -8
- package/apps/runtime/dist/services/runners.js +4 -3
- package/apps/runtime/dist/services/runs.js +3 -3
- package/apps/runtime/dist/services/site.js +2 -2
- package/apps/runtime/dist/services/space-categories.js +4 -4
- package/apps/runtime/dist/services/space-data.js +13 -13
- package/apps/runtime/dist/services/space-origin.js +1 -1
- package/apps/runtime/dist/services/spaces.js +7 -7
- package/apps/runtime/dist/services/wizards.js +5 -5
- package/apps/runtime/dist/tools/net-guard.js +135 -24
- package/apps/runtime/dist/tools/plugin.js +1 -1
- package/apps/runtime/dist/tools/store.js +1 -1
- package/apps/runtime/dist/widgets/step.js +1 -1
- package/apps/web/dist/assets/AboutDialog-DaYwk84X.js +1 -0
- package/apps/web/dist/assets/{ChangelogDialog-BXpkgatF.js → ChangelogDialog-CsYbEayb.js} +1 -1
- package/apps/web/dist/assets/{ChatView-t7z44uFN.js → ChatView-BRD3fKZU.js} +1 -1
- package/apps/web/dist/assets/{EditorPage-4qxNJgKr.js → EditorPage-ocPlZD3E.js} +3 -3
- package/apps/web/dist/assets/{FlowPreview-WpS8DCPl.js → FlowPreview-Bm7sv746.js} +1 -1
- package/apps/web/dist/assets/{Harness-DL7Bse40.js → Harness-DKE-YNA5.js} +1 -1
- package/apps/web/dist/assets/{NewWizardChannels-Crt6PzH2.js → NewWizardChannels-CnWckqjO.js} +1 -1
- package/apps/web/dist/assets/{NewWizardPage-COiVmNsl.js → NewWizardPage-BXTpbHVM.js} +1 -1
- package/apps/web/dist/assets/{OnboardingPage-BwluEqXq.js → OnboardingPage-3Rz5uOsa.js} +1 -1
- package/apps/web/dist/assets/{ProjectPage-BIRU_AlN.js → ProjectPage-QdSJwm3k.js} +1 -1
- package/apps/web/dist/assets/{PublicRunner-BxMb4gEt.js → PublicRunner-DEpBer5g.js} +1 -1
- package/apps/web/dist/assets/{ReadOnly-D9r5ze5S.js → ReadOnly-rr_RJD-a.js} +1 -1
- package/apps/web/dist/assets/{RunDrawer-DmJl2QOJ.js → RunDrawer-BsZt0tL9.js} +1 -1
- package/apps/web/dist/assets/{RunnerView-CF_1rC-7.js → RunnerView-BbRukEdE.js} +1 -1
- package/apps/web/dist/assets/SettingsPage-qkWsQIMN.js +1 -0
- package/apps/web/dist/assets/{SetupPage-BGKtbS7j.js → SetupPage-PzvPPLfM.js} +1 -1
- package/apps/web/dist/assets/{SharePage-C4MqXKDA.js → SharePage-7vdDWG1n.js} +1 -1
- package/apps/web/dist/assets/changelog-BFdAYD28.js +1 -0
- package/apps/web/dist/assets/{esm-CsY8TkyE.js → esm-g0kaGp8t.js} +1 -1
- package/apps/web/dist/assets/{index-BjQvGQp_.js → index-BzPid1oQ.js} +4 -4
- package/apps/web/dist/assets/{lock-CI6TpWL-.js → lock-BK9RYIft.js} +1 -1
- package/apps/web/dist/assets/oss-credits-BJrR7BR1.js +1 -0
- package/apps/web/dist/assets/{phone-BrtQz-fG.js → phone-DtkY0NfU.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-BtEKL72n.js → settings-menu-7EJQRFOi.js} +1 -1
- package/apps/web/dist/assets/{ui-4IaTD7LB.js → ui-B6S5hYPd.js} +3 -3
- package/apps/web/dist/assets/{upload-CWJAtPRo.js → upload-rYCAy7ox.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/apps/web/dist/mcp/flow.html +3 -3
- package/bin/wizards.mjs +1 -1
- package/node_modules/@engenty-wizards/plugin-sdk/dist/index.d.ts +21 -2
- package/node_modules/@engenty-wizards/shared/dist/projects.js +1 -1
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +48 -48
- package/node_modules/@engenty-wizards/shared/dist/run.js +48 -48
- package/package.json +5 -4
- package/apps/web/dist/assets/AboutDialog-A_ILyeue.js +0 -1
- package/apps/web/dist/assets/SettingsPage-3xSInE-A.js +0 -1
- package/apps/web/dist/assets/changelog-CM_GdIVI.js +0 -1
- package/apps/web/dist/assets/oss-credits-BQQX0kvk.js +0 -1
|
@@ -1,113 +1,121 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: WordPress
|
|
3
|
-
description: Put wizards on a WordPress site with the plugin
|
|
4
|
-
version: 0.
|
|
3
|
+
description: Put wizards on a WordPress site with the plugin “engenty wizards” – connect, read the site in, place a wizard, read results in the admin.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
The plugin **engenty wizards** puts the wizards of an engenty.ai account on a WordPress site and
|
|
8
8
|
shows what visitors left in the WordPress admin. The wizards run on engenty.ai: WordPress keeps
|
|
9
|
-
|
|
10
|
-
itself, with the site
|
|
9
|
+
the plugin’s settings and the connection, but no answers. On WordPress 7.0 a wizard can also run
|
|
10
|
+
on the site itself, with the site’s own AI provider and no account ([below](#without-an-account)).
|
|
11
11
|
|
|
12
12
|
| | |
|
|
13
13
|
|---|---|
|
|
14
14
|
| WordPress | 6.6 or newer; 7.0 or newer for wizards without an account |
|
|
15
15
|
| PHP | 8.1 or newer, nothing else on the host |
|
|
16
|
-
| Site address | https,
|
|
16
|
+
| Site address | https, so you can sign in to engenty.ai from the admin |
|
|
17
17
|
| Account | Free or above on engenty.ai; Contacts and Appointments need Pro |
|
|
18
18
|
|
|
19
19
|
## Install
|
|
20
20
|
|
|
21
|
-
Download `engenty-wizards.zip
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
Download `engenty-wizards.zip`, either in the studio under Settings → Integrate → WordPress
|
|
22
|
+
(“Download engenty-wizards.zip”) or from the
|
|
23
|
+
[releases](https://github.com/engenty/engenty-wizards-wp-plugin/releases/latest). Upload it in
|
|
24
|
+
WordPress under **Plugins → Add New → Upload Plugin** and activate it. The menu **engenty** then
|
|
24
25
|
opens.
|
|
25
26
|
|
|
26
27
|
## Connect
|
|
27
28
|
|
|
28
|
-
On **engenty → Overview
|
|
29
|
+
On **engenty → Overview** you have two ways in:
|
|
29
30
|
|
|
30
31
|
- **Create your own AI** offers a free account on engenty.ai: **Create a free account**.
|
|
31
|
-
- **Sign in**, under
|
|
32
|
+
- **Sign in**, under “Already have an engenty account?”, uses an account you already have.
|
|
32
33
|
|
|
33
|
-
engenty.ai asks you to allow the site access and sends you back
|
|
34
|
-
as a suggestion. The site is then connected as you: **Settings → Connection** shows
|
|
35
|
-
team and plan, and **Disconnect** ends the connection and revokes the access.
|
|
34
|
+
engenty.ai asks you to allow the site access and sends you back. Your WordPress email address
|
|
35
|
+
goes along as a suggestion. The site is then connected as you: **Settings → Connection** shows
|
|
36
|
+
the account, team and plan, and **Disconnect** ends the connection and revokes the access.
|
|
36
37
|
|
|
37
|
-
**By hand:** for your own engenty server, or where signing in through the browser
|
|
38
|
-
enter an **Address** and an **API key** under **Settings → Connect by hand**. On engenty.ai
|
|
39
|
-
|
|
40
|
-
with the address and an API key
|
|
38
|
+
**By hand:** for your own engenty server, or where signing in through the browser doesn’t work,
|
|
39
|
+
enter an **Address** and an **API key** under **Settings → Connect by hand**. On engenty.ai you
|
|
40
|
+
create the key under Account. On your own server you create it under Settings → Integrate, with
|
|
41
|
+
an app’s “Connect with the address and an API key” (see
|
|
42
|
+
[AI apps](./ai-apps.md#an-app-on-another-computer)).
|
|
43
|
+
|
|
44
|
+
The plugin connects to an account on engenty.ai, not to engenty wizards on your computer. If you
|
|
45
|
+
build on your computer, sign in to your account there and publish your wizards. You then choose
|
|
46
|
+
them in WordPress.
|
|
41
47
|
|
|
42
48
|
## Set up
|
|
43
49
|
|
|
44
|
-
After
|
|
50
|
+
After you connect, the overview walks you through three steps.
|
|
45
51
|
|
|
46
52
|
| Step | What happens |
|
|
47
53
|
|---|---|
|
|
48
|
-
| Read the website | The plugin reads the site from inside WordPress: name, tagline, logo, the theme
|
|
54
|
+
| Read the website | The plugin reads the site from inside WordPress: name, tagline, logo, the theme’s colours, email and phone from the imprint and contact pages, the shop’s address with WooCommerce, and the published pages as text. You untick what shouldn’t go. The rest fills in the space’s details where they are empty and goes into its [knowledge](./space.md#knowledge) as pages. engenty then reads the imprint and contact pages for the address, VAT ID, opening hours and who runs the business |
|
|
49
55
|
| Create the first wizard | A template becomes a wizard and goes live in one click |
|
|
50
|
-
| Put on the website | As a bubble on every page, on a new page (a draft with the wizard
|
|
56
|
+
| Put on the website | As a bubble on every page, on a new page (a draft with the wizard’s block, for you to publish), or placed by you (see below) |
|
|
51
57
|
|
|
52
|
-
Reading the site and making wizards
|
|
53
|
-
[
|
|
54
|
-
WordPress.
|
|
58
|
+
Reading the site and making wizards in WordPress needs Pro. On Free you build in
|
|
59
|
+
[engenty wizards on your computer](./install.md) and publish to your account. The wizards then
|
|
60
|
+
show up in WordPress.
|
|
55
61
|
|
|
56
62
|
## Put a wizard on a page
|
|
57
63
|
|
|
58
64
|
| Way | |
|
|
59
65
|
|---|---|
|
|
60
|
-
| Block **engenty Wizard** |
|
|
61
|
-
| Shortcode | `[engenty_wizard id="ID" mode="modal" label="Start a request"]
|
|
62
|
-
| Elementor | The widget **engenty Wizard
|
|
66
|
+
| Block **engenty Wizard** | Choose the wizard and how it shows: **In the text**, **Button + window** or **Bubble bottom right**, with a label, a line beside the bubble and a colour. With “In the text”, the editor shows a wizard from the account itself |
|
|
67
|
+
| Shortcode | `[engenty_wizard id="ID" mode="modal" label="Start a request"]`. `id` is the wizard’s ID or the token of its link; `mode` is `inline`, `modal` or `bubble`; `text` and `color` work as in the block |
|
|
68
|
+
| Elementor | The widget **engenty Wizard**, with the block’s choices |
|
|
63
69
|
| PHP | `<?php engenty_wizard( 'ID', [ 'mode' => 'inline' ] ); ?>` in a theme template |
|
|
64
|
-
| Bubble | **Settings → Bubble on every page**: one wizard at the bottom right of every page
|
|
70
|
+
| Bubble | **Settings → Bubble on every page**: one wizard at the bottom right of every page except the ones you leave out, with an optional line beside it and your colour |
|
|
65
71
|
|
|
66
|
-
A wizard
|
|
67
|
-
from the account, each way writes the share dialog
|
|
68
|
-
[website
|
|
72
|
+
A wizard’s drawer under **Wizards** has the shortcode and the PHP line ready to copy. For a wizard
|
|
73
|
+
from the account, each way writes the share dialog’s
|
|
74
|
+
[website code](./test-and-share.md#embed-in-a-website) with the page’s address, so a result says
|
|
69
75
|
which page it was started on.
|
|
70
76
|
|
|
71
77
|
## Results, contacts, appointments
|
|
72
78
|
|
|
73
79
|
| Page | Shows | Plan |
|
|
74
80
|
|---|---|---|
|
|
75
|
-
| Results | What visitors left: when, which wizard, the
|
|
81
|
+
| Results | What visitors left: when, which wizard, the email address and first answers, the page. A result opens with all answers, what the wizard made and its downloads | every plan |
|
|
76
82
|
| Contacts | The leads your wizards collected, with search and the wizard they came through | Pro, Team |
|
|
77
|
-
| Appointments | Upcoming, past and cancelled bookings
|
|
83
|
+
| Appointments | Upcoming, past and cancelled bookings in the space’s calendar | Pro, Team |
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
You set who sees these pages under **Settings → Access to results, contacts and appointments**.
|
|
86
|
+
Administrators always see them, and editors do from the start. engenty.ai keeps a visitor’s
|
|
87
|
+
result for 7 days.
|
|
81
88
|
|
|
82
89
|
## Without an account
|
|
83
90
|
|
|
84
91
|
A WordPress 7.0 site with its own AI provider (WordPress → **Settings → Connectors**: OpenAI,
|
|
85
|
-
Anthropic, Google, or Ollama through its provider plugin) runs wizards by itself
|
|
86
|
-
credits
|
|
87
|
-
offers the account first and, below it, **Local, with your own AI provider**.
|
|
88
|
-
then
|
|
92
|
+
Anthropic, Google, or Ollama through its provider plugin) runs wizards by itself. It needs no
|
|
93
|
+
account and no credits: the provider bills the site’s key. On **engenty → Overview**, **Create
|
|
94
|
+
your own AI** offers the account first and, below it, **Local, with your own AI provider**.
|
|
95
|
+
**Set up locally** then takes you through three steps: the provider (with a test), the wizards
|
|
96
|
+
and the website.
|
|
89
97
|
|
|
90
98
|
| | |
|
|
91
99
|
|---|---|
|
|
92
|
-
| Wizards | The templates that
|
|
93
|
-
| What runs | Pages and their fields; photos go to the provider where it takes images.
|
|
94
|
-
| What
|
|
95
|
-
| The check | The share dialog
|
|
96
|
-
| Knowledge |
|
|
97
|
-
| From the account | On a connected site with a provider, a published wizard
|
|
98
|
-
| Results | Kept in WordPress under **Results**, 90 days unless **Keep results** says otherwise
|
|
99
|
-
| Limits | 6 runs an hour per visitor and 50 a day per wizard, a honeypot
|
|
100
|
+
| Wizards | The templates that come with the plugin, chosen from the gallery, or a wizard file (`.wizard`) from a wizard’s share dialog in the studio (“Website” → “Without an account: as a package”). You take it in with **Import** on the **Wizards** page |
|
|
101
|
+
| What runs | Pages and their fields; photos go to the provider where it takes images. AI steps, which can also read a web page or call a public API where the step names `web_fetch` or `http` (the site does that itself). Decisions, branches, reviews and views. Documents and dashboards as HTML. Results as Markdown, text, CSV or JSON, HTML as a page to print, and a PDF of a written text, made in the visitor’s browser. A document’s PDF comes from the browser’s print |
|
|
102
|
+
| What doesn’t | Voice notes, sign-ins to connected accounts, choosing an appointment time, list fields, and a file a later step reads. Web search, the browser, code and image tools, connected systems (MCP servers) and plugin steps (Contacts, Appointments and the like). Widgets, films, and images, video and voice made by a model. Lists and the wizard’s memory. Word, Excel and other downloads |
|
|
103
|
+
| The check | The share dialog’s package view and, in the plugin, the gallery, the **Wizards** page and the import say for each wizard whether it “Runs there as is”, “Runs with less” or “Needs an account”. They list what it lacks in the gallery’s words (“not set up”, “works without”). With less, a choice on a page that leads to something the site lacks is closed there (“Not available here right now”), and a format falls away. The import refuses only a wizard that needs an account. A wizard that needs a plugin only behind a choice runs with less, with that choice closed |
|
|
104
|
+
| Knowledge | In the package view, **Take the knowledge along** puts the space’s pages into the package as files (up to 2 MB, each page up to 60,000 characters). It is a snapshot of the day it was packed. On the site, an AI step first gets the wizard’s own text files, then the pages that match the step best (its instructions and the answers so far), up to 60,000 characters in all |
|
|
105
|
+
| From the account | On a connected site with a provider, a published wizard’s drawer offers **Run here**. Its published version comes over and runs on the site with the site’s provider, without credits, and its results stay in WordPress. **Run through engenty.ai** switches back, and **Reload** fetches the published version again |
|
|
106
|
+
| Results | Kept in WordPress under **Results**, for 90 days unless **Keep results** says otherwise. Nothing goes to engenty.ai |
|
|
107
|
+
| Limits | 6 runs an hour per visitor and 50 a day per wizard, plus a honeypot. 60 seconds per AI step, up to 600 for a slow local model (the setting also raises the Ollama provider plugin’s own limit) |
|
|
100
108
|
|
|
101
109
|
The settings for all of this are under **Settings → Standalone wizards**: the limits, how long
|
|
102
|
-
results are kept, photos to the provider, and the switch that lets wizards read web
|
|
103
|
-
public APIs. The browser follows the wizard
|
|
104
|
-
wizard
|
|
105
|
-
Both kinds can be on one site: under **Wizards
|
|
106
|
-
**Local**.
|
|
110
|
+
results are kept, whether photos go to the provider, and the switch that lets wizards read web
|
|
111
|
+
pages and call public APIs. The visitor’s browser follows the wizard’s flow and draws every page.
|
|
112
|
+
WordPress keeps the wizard’s prompts and the run, and asks the provider for each AI step through
|
|
113
|
+
its AI Client. Both kinds can be on one site: under **Wizards**, the ones that run on the site
|
|
114
|
+
are marked **Local**.
|
|
107
115
|
|
|
108
116
|
## Privacy
|
|
109
117
|
|
|
110
118
|
Visitors talk to engenty.ai directly from the frame the wizard runs in. Name engenty in your
|
|
111
|
-
privacy statement
|
|
112
|
-
site send the visitors
|
|
113
|
-
that names
|
|
119
|
+
privacy statement: **Settings → Privacy** has a sentence to start from. Wizards that run on the
|
|
120
|
+
site send the visitors’ answers to the site’s AI provider instead. For those, the settings give
|
|
121
|
+
a sentence that names the provider.
|
|
@@ -170,7 +170,7 @@ async function read(input, opts) {
|
|
|
170
170
|
const vision = new VisionProvider(opts.charge, opts.signal, opts.call);
|
|
171
171
|
if (mime.startsWith("image/")) {
|
|
172
172
|
if (!vision.canConvert(mime)) {
|
|
173
|
-
throw new UnreadableDocument(bilingual(`Bilder vom Typ ${mime}
|
|
173
|
+
throw new UnreadableDocument(bilingual(`Bilder vom Typ ${mime} lassen sich nicht lesen (PNG, JPEG und WebP gehen).`, `Images of type ${mime} can’t be read (PNG, JPEG and WebP work).`));
|
|
174
174
|
}
|
|
175
175
|
const result = await vision.convert(data, name, mime);
|
|
176
176
|
return { markdown: result.markdown, pages: 1, via: "vision" };
|
|
@@ -214,7 +214,7 @@ async function read(input, opts) {
|
|
|
214
214
|
if (mime === "application/json" || mime.startsWith("text/")) {
|
|
215
215
|
return { markdown: text(), pages: null, via: "text" };
|
|
216
216
|
}
|
|
217
|
-
throw new UnreadableDocument(bilingual(`„${name}“ (${mime})
|
|
217
|
+
throw new UnreadableDocument(bilingual(`„${name}“ (${mime}) lässt sich nicht lesen.`, `“${name}” (${mime}) can’t be read.`));
|
|
218
218
|
}
|
|
219
219
|
// --- structured extraction -----------------------------------------------------
|
|
220
220
|
/** The scanner's schemas say nothing about the currency; SaaS invoices come in several. */
|
|
@@ -1,3 +1,19 @@
|
|
|
1
1
|
/** Stand-in for `@engenty/web-ingest`: its host guard, and this product's HTML to Markdown. */
|
|
2
|
+
import { isPublicAddress } from "../../tools/net-guard.js";
|
|
3
|
+
import { assertPublicHttpHost as assertHost, isBlockedIp as blockedIp, } from "../web-ingest/ssrf.js";
|
|
2
4
|
export { htmlToMarkdown } from "../../render/convert.js";
|
|
3
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The copied guard misses IPv6 forms of private IPv4 addresses (NAT64, 6to4, ::a.b.c.d) and some
|
|
7
|
+
* special ranges; every address it lets through is checked again with the runtime's own range check.
|
|
8
|
+
*/
|
|
9
|
+
export function isBlockedIp(ip) {
|
|
10
|
+
return blockedIp(ip) || !isPublicAddress(ip);
|
|
11
|
+
}
|
|
12
|
+
export async function assertPublicHttpHost(urlString, lookupImpl) {
|
|
13
|
+
const result = await assertHost(urlString, lookupImpl);
|
|
14
|
+
const bad = result.addresses.find((a) => !isPublicAddress(a));
|
|
15
|
+
if (bad) {
|
|
16
|
+
throw new Error(`URL host is not allowed for fetch: ${result.url.hostname} (${bad})`);
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
@@ -149,14 +149,14 @@ export function readPageInput(step, input, context = {}) {
|
|
|
149
149
|
if (field.min && v.length < field.min) {
|
|
150
150
|
errors.push({
|
|
151
151
|
field: field.id,
|
|
152
|
-
message: bilingual(`
|
|
152
|
+
message: bilingual(`Wähl mindestens ${field.min} aus`, `Choose at least ${field.min}`),
|
|
153
153
|
});
|
|
154
154
|
continue;
|
|
155
155
|
}
|
|
156
156
|
if (field.max && v.length > field.max) {
|
|
157
157
|
errors.push({
|
|
158
158
|
field: field.id,
|
|
159
|
-
message: bilingual(`Höchstens ${field.max} –
|
|
159
|
+
message: bilingual(`Höchstens ${field.max} – entferne einige`, `At most ${field.max} – remove some`),
|
|
160
160
|
});
|
|
161
161
|
continue;
|
|
162
162
|
}
|
|
@@ -164,7 +164,7 @@ export function readPageInput(step, input, context = {}) {
|
|
|
164
164
|
if (field.kind === "number" && Number.isNaN(v)) {
|
|
165
165
|
errors.push({
|
|
166
166
|
field: field.id,
|
|
167
|
-
message: bilingual("
|
|
167
|
+
message: bilingual("Gib eine Zahl ein", "Enter a number"),
|
|
168
168
|
});
|
|
169
169
|
continue;
|
|
170
170
|
}
|
|
@@ -175,7 +175,7 @@ export function readPageInput(step, input, context = {}) {
|
|
|
175
175
|
if (field.kind === "slot" && !empty(v) && !field.options?.includes(String(v))) {
|
|
176
176
|
errors.push({
|
|
177
177
|
field: field.id,
|
|
178
|
-
message: bilingual("Dieser Termin wird nicht angeboten", "This time
|
|
178
|
+
message: bilingual("Dieser Termin wird nicht angeboten", "This time isn’t offered"),
|
|
179
179
|
});
|
|
180
180
|
continue;
|
|
181
181
|
}
|
|
@@ -6,12 +6,12 @@ const TEXT = {
|
|
|
6
6
|
en: {
|
|
7
7
|
done: "Your result is ready.",
|
|
8
8
|
failed: "The run stopped with an error.",
|
|
9
|
-
waiting: "The wizard
|
|
9
|
+
waiting: "The wizard is waiting for you.",
|
|
10
10
|
asks: "The wizard has a question for you.",
|
|
11
11
|
},
|
|
12
12
|
de: {
|
|
13
13
|
done: "Dein Ergebnis ist bereit.",
|
|
14
|
-
failed: "Der
|
|
14
|
+
failed: "Der Lauf ist mit einem Fehler stehen geblieben.",
|
|
15
15
|
waiting: "Der Wizard wartet auf dich.",
|
|
16
16
|
asks: "Der Wizard hat eine Frage an dich.",
|
|
17
17
|
},
|
|
@@ -43,7 +43,7 @@ export class RunInputError extends NotedError {
|
|
|
43
43
|
}
|
|
44
44
|
export class NoCreditsError extends NotedError {
|
|
45
45
|
constructor() {
|
|
46
|
-
super(bilingual("Dieser Wizard hat gerade kein Guthaben mehr.
|
|
46
|
+
super(bilingual("Dieser Wizard hat gerade kein Guthaben mehr. Versuch es später noch einmal.", "This wizard has run out of credits for now. Try again later."));
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
/** The runs this process drives right now, with the handle that stops each. */
|
|
@@ -113,19 +113,19 @@ function friendly(err) {
|
|
|
113
113
|
}
|
|
114
114
|
// A runtime that runs alone pays its provider itself: its admin can top the account up.
|
|
115
115
|
if (!managed && /minimum balance|insufficient_funds|top up your credits/i.test(msg)) {
|
|
116
|
-
return bilingual("Das Guthaben beim
|
|
116
|
+
return bilingual("Das Guthaben beim Modellanbieter reicht dafür nicht aus (Videos brauchen dort ein Mindestguthaben). Lade dort auf und versuch es noch einmal.", "Your credit with the model provider isn’t enough for this (videos need a minimum balance there). Top up there and try again.");
|
|
117
117
|
}
|
|
118
118
|
if (/rate.?limit|429/i.test(msg)) {
|
|
119
|
-
return bilingual("Der KI-Dienst ist gerade ausgelastet.
|
|
119
|
+
return bilingual("Der KI-Dienst ist gerade ausgelastet. Versuch es gleich noch einmal.", "The AI service is busy right now. Try again in a moment.");
|
|
120
120
|
}
|
|
121
121
|
if (/timeout|timed out/i.test(msg)) {
|
|
122
|
-
return bilingual("Der Schritt hat zu lange gedauert.
|
|
122
|
+
return bilingual("Der Schritt hat zu lange gedauert. Versuch es noch einmal.", "The step took too long. Try again.");
|
|
123
123
|
}
|
|
124
124
|
// The platform's own provider account (budget, quota, key): nothing the person can fix.
|
|
125
125
|
if (/budget|quota|insufficient|billing|credit balance|api key|unauthori[sz]ed|401|403/i.test(msg)) {
|
|
126
|
-
return bilingual("Der KI-Dienst ist gerade nicht erreichbar.
|
|
126
|
+
return bilingual("Der KI-Dienst ist gerade nicht erreichbar. Versuch es später noch einmal.", "The AI service can’t be reached right now. Try again later.");
|
|
127
127
|
}
|
|
128
|
-
return bilingual(`Dieser Schritt
|
|
128
|
+
return bilingual(`Dieser Schritt hat nicht geklappt: ${msg.slice(0, 300)}`, `This step failed: ${msg.slice(0, 300)}`);
|
|
129
129
|
}
|
|
130
130
|
/**
|
|
131
131
|
* A step that failed ends the run. A failure with a note (Apple Intelligence's) goes into the log
|
|
@@ -637,7 +637,7 @@ export async function submitPage(runId, stepId, input) {
|
|
|
637
637
|
(choice.values.length === 0 || choice.values.some((v) => String(v) === String(answer)))) {
|
|
638
638
|
errors.push({
|
|
639
639
|
field: id,
|
|
640
|
-
message: bilingual("Das ist hier gerade nicht verfügbar.", "That
|
|
640
|
+
message: bilingual("Das ist hier gerade nicht verfügbar.", "That isn’t available here right now."),
|
|
641
641
|
});
|
|
642
642
|
}
|
|
643
643
|
}
|
|
@@ -667,7 +667,7 @@ export async function submitPage(runId, stepId, input) {
|
|
|
667
667
|
}
|
|
668
668
|
else if (field.required) {
|
|
669
669
|
throw new RunInputError([
|
|
670
|
-
{ field: field.id, message: bilingual("
|
|
670
|
+
{ field: field.id, message: bilingual("Verbinde zuerst", "Connect first") },
|
|
671
671
|
]);
|
|
672
672
|
}
|
|
673
673
|
}
|
|
@@ -554,7 +554,7 @@ export async function runAgentStep(step, ctx) {
|
|
|
554
554
|
const text = step.output.format === "json" ? everything : closing || everything;
|
|
555
555
|
if (step.output.format !== "json") {
|
|
556
556
|
if (!text && !assets.length) {
|
|
557
|
-
throw new StepError(bilingual("Der Schritt hat kein Ergebnis geliefert.", "The step
|
|
557
|
+
throw new StepError(bilingual("Der Schritt hat kein Ergebnis geliefert.", "The step didn’t return a result."));
|
|
558
558
|
}
|
|
559
559
|
return { text, assets: assets.length ? assets : undefined, at: new Date().toISOString() };
|
|
560
560
|
}
|
|
@@ -755,7 +755,7 @@ async function writeHtml(step, ctx, kind) {
|
|
|
755
755
|
.replace(/```\s*$/, "")
|
|
756
756
|
.trim();
|
|
757
757
|
if (!/<html|<!doctype/i.test(html)) {
|
|
758
|
-
throw new StepError(bilingual("Das Dokument konnte nicht erstellt werden.", "The document
|
|
758
|
+
throw new StepError(bilingual("Das Dokument konnte nicht erstellt werden.", "The document couldn’t be created."));
|
|
759
759
|
}
|
|
760
760
|
// On screen (preview, PNG) a print document needs the margin its @page rule gives it on paper.
|
|
761
761
|
return kind === "document"
|
|
@@ -14,7 +14,7 @@ export async function runSurfaceStep(step, ctx) {
|
|
|
14
14
|
const components = step.components ?? (await decidedComponents(step, ctx));
|
|
15
15
|
const issues = validateSurface(components, Object.keys(data));
|
|
16
16
|
if (issues.length) {
|
|
17
|
-
throw new StepError(bilingual(`Die Ansicht
|
|
17
|
+
throw new StepError(bilingual(`Die Ansicht hat Fehler: ${issues.map((i) => i.message).join(" ")}`, `The view has errors: ${issues.map((i) => i.message).join(" ")}`));
|
|
18
18
|
}
|
|
19
19
|
return { surface: { components, data }, at: new Date().toISOString() };
|
|
20
20
|
}
|
|
@@ -229,13 +229,13 @@ export async function runFilmStep(step, ctx) {
|
|
|
229
229
|
if (ctx.signal.aborted) {
|
|
230
230
|
throw err;
|
|
231
231
|
}
|
|
232
|
-
throw new StepError(bilingual(`${client.name} hat beim Film aufgehört: ${err.message}. Die Arbeit ist gespeichert
|
|
232
|
+
throw new StepError(bilingual(`${client.name} hat beim Film aufgehört: ${err.message}. Die Arbeit ist gespeichert. Ein neuer Versuch macht dort weiter.`, `${client.name} stopped working on the film: ${err.message}. The work is saved. A new try carries on from there.`));
|
|
233
233
|
});
|
|
234
234
|
const result = last;
|
|
235
235
|
if (!result || result.is_error) {
|
|
236
236
|
const detail = String(result?.result ?? (stderr.trim() || "no result")).slice(0, 400);
|
|
237
237
|
const failure = failureOf(client, detail);
|
|
238
|
-
throw new StepError(bilingual(`${errorText(failure, "de")} Die Arbeit ist gespeichert
|
|
238
|
+
throw new StepError(bilingual(`${errorText(failure, "de")} Die Arbeit ist gespeichert. Ein neuer Versuch macht dort weiter.`, `${errorText(failure, "en")} The work is saved. A new try carries on from there.`));
|
|
239
239
|
}
|
|
240
240
|
return result;
|
|
241
241
|
};
|
|
@@ -265,7 +265,7 @@ export async function runFilmStep(step, ctx) {
|
|
|
265
265
|
}
|
|
266
266
|
const problem = renderProblem(render.out);
|
|
267
267
|
if (attempt >= RENDER_FIXES) {
|
|
268
|
-
throw new StepError(bilingual(`Der Film ließ sich nicht rendern: ${problem.slice(0, 400)}`, `The film
|
|
268
|
+
throw new StepError(bilingual(`Der Film ließ sich nicht rendern: ${problem.slice(0, 400)}`, `The film couldn’t be rendered: ${problem.slice(0, 400)}`));
|
|
269
269
|
}
|
|
270
270
|
await ctx.emit("tool", { code: "filmFix" });
|
|
271
271
|
const fixed = await turn(`The final render of film/ failed:\n\n${problem}\n\nFind the cause in the composition's code, fix it, run \`check\` and a draft render through the hyperframes tool until both pass, and end with one line on what you fixed.`, await savedSession(root));
|
|
@@ -143,5 +143,5 @@ export const claude = {
|
|
|
143
143
|
},
|
|
144
144
|
login: { args: ["auth", "login"], interactive: false },
|
|
145
145
|
model: (alias, effort) => new ClaudeCodeModel(claude, alias || "sonnet", effort),
|
|
146
|
-
exhausted: bilingual("Das Anthropic-Konto, mit dem Claude Code angemeldet ist, hat kein Guthaben. Melde Claude Code mit deinem Abo an
|
|
146
|
+
exhausted: bilingual("Das Anthropic-Konto, mit dem Claude Code angemeldet ist, hat kein Guthaben. Melde Claude Code unter Einstellungen → Modelle mit deinem Abo an.", "The Anthropic account Claude Code is signed in with has no credit. Sign Claude Code in with your subscription under Settings → Models."),
|
|
147
147
|
};
|
|
@@ -225,5 +225,5 @@ export const codex = {
|
|
|
225
225
|
login: { args: ["login"], interactive: false },
|
|
226
226
|
model: (alias, effort) => new CodexModel(codex, alias || "default", effort),
|
|
227
227
|
image: { alias: "image", model: (alias) => new CodexImageModel(codex, alias || "image") },
|
|
228
|
-
exhausted: bilingual("Das Kontingent des ChatGPT-Kontos, mit dem Codex angemeldet ist, ist aufgebraucht.
|
|
228
|
+
exhausted: bilingual("Das Kontingent des ChatGPT-Kontos, mit dem Codex angemeldet ist, ist aufgebraucht. Versuch es später noch einmal oder wähle einen anderen Client.", "The ChatGPT account Codex is signed in with has used up its quota. Try again later or choose another client."),
|
|
229
229
|
};
|
|
@@ -8,8 +8,8 @@ import { openBridge } from "../mcp/bridge.js";
|
|
|
8
8
|
import { ModelUnavailableError } from "../model-errors.js";
|
|
9
9
|
import { extensionOf, jsonInstruction, parseJsonAnswer, renderPrompt } from "./prompt.js";
|
|
10
10
|
const workDir = join(env.dataDir, "harness");
|
|
11
|
-
export const signedOut = (h) => bilingual(`${h.name} ist auf diesem
|
|
12
|
-
export const notInstalled = (h) => bilingual(`${h.name} ist auf diesem
|
|
11
|
+
export const signedOut = (h) => bilingual(`${h.name} ist auf diesem Computer nicht angemeldet. Melde dich unter Einstellungen → Modelle an.`, `${h.name} isn’t signed in on this computer. Sign in under Settings → Models.`);
|
|
12
|
+
export const notInstalled = (h) => bilingual(`${h.name} ist auf diesem Computer nicht installiert. Installiere es unter Einstellungen → Modelle.`, `${h.name} isn’t installed on this computer. Install it under Settings → Models.`);
|
|
13
13
|
export const exhausted = (h) => h.exhausted ??
|
|
14
14
|
bilingual(`Das Konto, mit dem ${h.name} angemeldet ist, hat kein Guthaben oder Kontingent mehr.`, `The account ${h.name} is signed in with has no credit or quota left.`);
|
|
15
15
|
/** The failure a client reports, as the person should read it. */
|
|
@@ -37,7 +37,7 @@ async function ptyModule() {
|
|
|
37
37
|
return { spawn };
|
|
38
38
|
}
|
|
39
39
|
catch {
|
|
40
|
-
throw new ServiceError("refused", bilingual("Das eingebaute Terminal ist auf diesem
|
|
40
|
+
throw new ServiceError("refused", bilingual("Das eingebaute Terminal ist auf diesem Computer nicht verfügbar. Führe den Befehl in deinem eigenen Terminal aus.", "The built-in terminal isn’t available on this computer. Run the command in your own terminal."));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
function emit(session, event) {
|
|
@@ -85,7 +85,7 @@ export async function openTerminal(opts) {
|
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
catch (err) {
|
|
88
|
-
throw new ServiceError("refused", bilingual(`Der Befehl konnte nicht starten: ${err.message}`, `The command
|
|
88
|
+
throw new ServiceError("refused", bilingual(`Der Befehl konnte nicht starten: ${err.message}`, `The command couldn’t start: ${err.message}`));
|
|
89
89
|
}
|
|
90
90
|
const session = {
|
|
91
91
|
id,
|
|
@@ -147,7 +147,7 @@ export async function openTerminal(opts) {
|
|
|
147
147
|
function sessionOf(id) {
|
|
148
148
|
const session = sessions.get(id);
|
|
149
149
|
if (!session) {
|
|
150
|
-
throw new ServiceError("not_found", bilingual("Dieses Terminal gibt es nicht mehr.", "This terminal
|
|
150
|
+
throw new ServiceError("not_found", bilingual("Dieses Terminal gibt es nicht mehr.", "This terminal no longer exists."));
|
|
151
151
|
}
|
|
152
152
|
return session;
|
|
153
153
|
}
|
|
@@ -9,7 +9,7 @@ import { noteRequest } from "./seen.js";
|
|
|
9
9
|
import { registerPrompts, registerTools } from "./tools.js";
|
|
10
10
|
const INSTRUCTIONS = `engenty wizards: page-by-page AI wizards — the person answers pages, AI steps write, research and make images or videos, the person reviews, the result is files.
|
|
11
11
|
Use one: list_wizards, then run_wizard straight away — its widget shows the wizard itself (show_wizard only when the person wants to see a wizard before running it), then follow waitingFor (answer_page, review_step, answer_ask, get_run with waitSeconds). Runs spend credits.
|
|
12
|
-
Build one: get_authoring_guide (schema + design rules), a close starter with get_starter, create_wizard, edit_wizard until "issues" is empty, check with start_test_run + get_test_run. Publish only when the
|
|
12
|
+
Build one: get_authoring_guide (schema + design rules), a close starter with get_starter, create_wizard, edit_wizard until "issues" is empty, check with start_test_run + get_test_run. Publish only when the person asks.
|
|
13
13
|
When a run needs the browser, hand over its browserUrl, the wizard's own run page. The studioUrl is for building only: never send someone who uses a wizard to the studio.
|
|
14
14
|
Projects are called spaces in the studio. Ids are for the tools only: name wizards and spaces by their titles and names, and where two spaces share a name, by where each comes from.`;
|
|
15
15
|
/** A wizard definition is a few KB; this leaves room and refuses anything far beyond it. */
|
|
@@ -40,7 +40,7 @@ export function mcpHandler() {
|
|
|
40
40
|
}
|
|
41
41
|
const who = principalOf(authInfo);
|
|
42
42
|
if ((await tenantStatus(who.tenantId)) === "suspended") {
|
|
43
|
-
return new Response(JSON.stringify({ error: "tenant_suspended" }), { status: 403 });
|
|
43
|
+
return new Response(JSON.stringify({ error: "This account is suspended.", code: "tenant_suspended" }), { status: 403 });
|
|
44
44
|
}
|
|
45
45
|
if (request.method === "POST") {
|
|
46
46
|
const body = await request
|
|
@@ -20,7 +20,7 @@ const note = z
|
|
|
20
20
|
.string()
|
|
21
21
|
.max(500)
|
|
22
22
|
.optional()
|
|
23
|
-
.describe("One sentence for the
|
|
23
|
+
.describe("One sentence for the person about what changed, in their language. Shown in the studio.");
|
|
24
24
|
const baseRevision = z
|
|
25
25
|
.number()
|
|
26
26
|
.int()
|
|
@@ -104,7 +104,7 @@ export function registerTools(server, who) {
|
|
|
104
104
|
title: "Authoring guide",
|
|
105
105
|
description: "Read this before writing a wizard: the JSON schema, field kinds, step types and tools, templates, design rules, and the MCP servers of the project.",
|
|
106
106
|
input: z.object({
|
|
107
|
-
projectId: z.string().optional().describe("Defaults to the
|
|
107
|
+
projectId: z.string().optional().describe("Defaults to the person's first project."),
|
|
108
108
|
}),
|
|
109
109
|
readOnly: true,
|
|
110
110
|
}, async ({ projectId }) => {
|
|
@@ -177,7 +177,7 @@ export function registerTools(server, who) {
|
|
|
177
177
|
});
|
|
178
178
|
tool("list_projects", "wizards:read", {
|
|
179
179
|
title: "List projects",
|
|
180
|
-
description: "The
|
|
180
|
+
description: "The person's projects, called spaces in the studio. Each holds wizards, a brand and MCP servers. Name a space by its name; where two share one, add where it comes from (`from`). Ids are for the tools: never show them to the person.",
|
|
181
181
|
input: z.object({}),
|
|
182
182
|
readOnly: true,
|
|
183
183
|
}, async () => (await listProjects(who.userId)).map((p) => ({
|
|
@@ -188,7 +188,7 @@ export function registerTools(server, who) {
|
|
|
188
188
|
})));
|
|
189
189
|
tool("list_wizards", "wizards:read", {
|
|
190
190
|
title: "List wizards",
|
|
191
|
-
description: "The
|
|
191
|
+
description: "The person's wizards, newest first, each with its space's name and where that space comes from. Ids are for the tools: never show them to the person.",
|
|
192
192
|
input: z.object({ projectId: z.string().optional() }),
|
|
193
193
|
readOnly: true,
|
|
194
194
|
}, async ({ projectId }) => {
|
|
@@ -251,7 +251,7 @@ export function registerTools(server, who) {
|
|
|
251
251
|
title: "Create wizard",
|
|
252
252
|
description: "Create a wizard from your JSON, or copy a starter. The draft may still have issues; fix them with edit_wizard.",
|
|
253
253
|
input: z.object({
|
|
254
|
-
projectId: z.string().optional().describe("Defaults to the
|
|
254
|
+
projectId: z.string().optional().describe("Defaults to the person's first project."),
|
|
255
255
|
definition: definition.optional(),
|
|
256
256
|
starterId: z.string().optional().describe("Copy this starter instead of sending JSON."),
|
|
257
257
|
note,
|
|
@@ -295,7 +295,7 @@ Returns the new revision and the issues.`,
|
|
|
295
295
|
// --- publish ---------------------------------------------------------------
|
|
296
296
|
tool("publish_wizard", "wizards:publish", {
|
|
297
297
|
title: "Publish wizard",
|
|
298
|
-
description: "Publish the draft as a new version behind the share link. Refused while the draft has issues. Only when the
|
|
298
|
+
description: "Publish the draft as a new version behind the share link. Refused while the draft has issues. Only when the person asked for it.",
|
|
299
299
|
input: z.object({ wizardId: z.string() }),
|
|
300
300
|
}, async ({ wizardId }) => publishAndSync(who.userId, wizardId));
|
|
301
301
|
tool("set_sharing", "wizards:publish", {
|
|
@@ -321,7 +321,7 @@ Returns the new revision and the issues.`,
|
|
|
321
321
|
// --- test runs ---------------------------------------------------------------
|
|
322
322
|
appTool("start_test_run", "runs:test", {
|
|
323
323
|
title: "Start test run",
|
|
324
|
-
description: "Run the draft once with your answers.
|
|
324
|
+
description: "Run the draft once with your answers. Spends the person's credits (short copy + image about 15, research about 150, video about 250). Pages are filled from `answers`, reviews accepted when acceptReviews is true. Follow it with get_test_run. Shows the flow with the run on it.",
|
|
325
325
|
input: z.object({
|
|
326
326
|
wizardId: z.string(),
|
|
327
327
|
answers: z
|
|
@@ -452,7 +452,7 @@ While status is running, get_run with waitSeconds. Hosts with MCP Apps also show
|
|
|
452
452
|
return runReport(who.userId, runId, waitSeconds);
|
|
453
453
|
});
|
|
454
454
|
tool("answer_ask", "runs:test", {
|
|
455
|
-
title: "Answer
|
|
455
|
+
title: "Answer confirmation",
|
|
456
456
|
description: "A running step asks before it changes something in a connected account (waitingFor.ask, kind confirm): allow it once, or skip it. Ask the person first.",
|
|
457
457
|
input: z.object({
|
|
458
458
|
runId: z.string(),
|
|
@@ -466,7 +466,7 @@ While status is running, get_run with waitSeconds. Hosts with MCP Apps also show
|
|
|
466
466
|
});
|
|
467
467
|
tool("control_run", "runs:test", {
|
|
468
468
|
title: "Control run",
|
|
469
|
-
description: "back: to the previous page or review. retry:
|
|
469
|
+
description: "back: return to the previous page or review. retry: run the failed step again. cancel: stop the run.",
|
|
470
470
|
input: z.object({ runId: z.string(), action: z.enum(["back", "retry", "cancel"]) }),
|
|
471
471
|
}, async ({ runId, action }) => {
|
|
472
472
|
await controlRun(who.userId, runId, action);
|