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
package/README.md
CHANGED
|
@@ -10,32 +10,28 @@
|
|
|
10
10
|
Let AI do the work.
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
<p align="center">
|
|
14
|
-
<img src="docs/assets/setup.png" alt="The first start of engenty wizards: choose the engine it thinks with — Codex, Claude Code, Gemini CLI, Cursor Agent or your own keys">
|
|
15
|
-
</p>
|
|
16
|
-
|
|
17
13
|
## What it does
|
|
18
14
|
|
|
19
|
-
- **Describe it, get a wizard.** Say in plain words what you do again and again
|
|
20
|
-
an image, a research briefing, an invoice, a quote, a damage report
|
|
15
|
+
- **Describe it, get a wizard.** Say in plain words what you do again and again – a post with
|
|
16
|
+
an image, a research briefing, an invoice, a quote, a damage report – and engenty builds a
|
|
21
17
|
wizard for it: pages that ask what it needs, AI steps that do the work.
|
|
22
18
|
- **AI steps do the work.** They research the web, write, draw images, render video, read PDFs,
|
|
23
|
-
scans and
|
|
19
|
+
scans and emails, build documents and dashboards, and write into other services over MCP, HTTP
|
|
24
20
|
or a browser. Anything that changes an account asks first.
|
|
25
21
|
- **Share it with a link.** Anyone can run a wizard in the browser, on a phone too: camera,
|
|
26
22
|
code scan, voice notes, location and a drawn signature included. Results download as PDF,
|
|
27
|
-
Word, HTML, Markdown, PNG, MP4, CSV, Excel or JSON, or go out as a link.
|
|
28
|
-
- **Runs on your machine, on your subscription.** It
|
|
23
|
+
Word, HTML, Markdown, PNG, MP4, MP3, CSV, Excel or JSON, or go out as a link.
|
|
24
|
+
- **Runs on your machine, on your subscription.** It uses Codex, Claude Code, Gemini CLI
|
|
29
25
|
or Cursor Agent when one is installed and signed in, so no API key is needed. Or bring a key
|
|
30
26
|
(Vercel AI Gateway, OpenAI, Anthropic), or a local model through Ollama. Your wizards and
|
|
31
27
|
results stay in a folder on your machine.
|
|
32
28
|
|
|
33
29
|
## How it looks
|
|
34
30
|
|
|
35
|
-
The studio: a wizard
|
|
31
|
+
The studio: a wizard’s steps as a flow with its branches, next to the conversation that changes them.
|
|
36
32
|
|
|
37
33
|
<p align="center">
|
|
38
|
-
<img src="docs/assets/studio.png" alt="The studio of engenty wizards: the flow of a wizard that collects a month's receipts for bookkeeping
|
|
34
|
+
<img src="docs/assets/studio.png" alt="The studio of engenty wizards: the flow of a wizard that collects a month's receipts for bookkeeping – two pages of questions, AI steps that branch to the inbox and to customer portals, a review and the result – with the conversation beside it">
|
|
39
35
|
</p>
|
|
40
36
|
|
|
41
37
|
A wizard in use: it asks on one page, then on the next, and ends with the result to download or share.
|
|
@@ -46,14 +42,14 @@ A wizard in use: it asks on one page, then on the next, and ends with the result
|
|
|
46
42
|
|
|
47
43
|
## Get started
|
|
48
44
|
|
|
49
|
-
Create an account at [engenty.ai](https://engenty.ai): it is in a closed beta, so
|
|
50
|
-
takes your
|
|
45
|
+
Create an account at [engenty.ai](https://engenty.ai): it is in a closed beta, so “Get started”
|
|
46
|
+
takes your email for an invitation, or your invitation code. Signed in, the studio asks who
|
|
51
47
|
your team is, reads your website into your space, takes first documents, and you build your
|
|
52
|
-
first wizard in the browser. Links run day and night on the team
|
|
48
|
+
first wizard in the browser. Links run day and night on the team’s credits.
|
|
53
49
|
|
|
54
50
|
## Install it on your computer
|
|
55
51
|
|
|
56
|
-
The same account on your own machine: it
|
|
52
|
+
The same account on your own machine: it runs on your Claude, ChatGPT, Gemini or Cursor
|
|
57
53
|
subscription, reads your local files and browses for you, and what you publish keeps running in
|
|
58
54
|
the cloud behind the same links. On macOS or Linux, in a terminal:
|
|
59
55
|
|
|
@@ -65,19 +61,23 @@ It needs nothing but `curl` and `tar` and asks for no password. It brings its ow
|
|
|
65
61
|
Node you already have is left alone), installs engenty wizards into `~/.engenty/wizards` and
|
|
66
62
|
then walks you through the rest:
|
|
67
63
|
|
|
68
|
-
- **Your engenty account.**
|
|
69
|
-
|
|
64
|
+
- **Your engenty account.** “Sign in now?”: a code and the browser for the sign-in; what you
|
|
65
|
+
publish on this computer then runs in the cloud too. Say no, and `wizards account sign-in`
|
|
66
|
+
does it any time.
|
|
70
67
|
`--local` leaves the account out: nothing leaves the computer, links answer on it only
|
|
71
68
|
([local only](https://engenty.ai/docs/user/local-only)).
|
|
72
|
-
- **
|
|
73
|
-
offers to install
|
|
69
|
+
- **An AI client.** It looks for Codex, Claude Code, Gemini CLI and Cursor Agent and
|
|
70
|
+
offers to install the missing ones – first the one whose app (Claude, ChatGPT, Cursor) is
|
|
74
71
|
on your Mac, as its subscription is most likely yours already. The first page of the studio
|
|
75
|
-
installs them too. Or use your account
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
installs them too. Or use your account’s credits, an API key, [Ollama](https://ollama.com) or,
|
|
73
|
+
on a Mac with Apple silicon and macOS 26, Apple Intelligence.
|
|
74
|
+
- **A browser and ffmpeg** (optional): Chrome, Edge or Chromium (on a Mac also Brave) for PDF
|
|
75
|
+
and PNG exports and for steps that use a browser, ffmpeg for MP4 videos of animated widgets.
|
|
78
76
|
- **Start at login** (optional): engenty wizards starts in the background when you log in (a
|
|
79
77
|
LaunchAgent on a Mac, a systemd user service on Linux). Links and AI clients then always
|
|
80
78
|
reach it. `wizards autostart on` or `off` switches it later.
|
|
79
|
+
- **Your AI apps** (optional): adds your wizards to the AI apps it finds, such as Claude
|
|
80
|
+
Desktop, Cursor or Codex. `wizards connect` and `wizards disconnect` do it later.
|
|
81
81
|
|
|
82
82
|
It starts nothing. Afterwards:
|
|
83
83
|
|
|
@@ -86,6 +86,7 @@ wizards start
|
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
starts it and opens the studio; it runs while that terminal is open, Ctrl-C stops it.
|
|
89
|
+
`wizards start -s` starts it in the background instead.
|
|
89
90
|
`wizards` opens a menu with all of it, `wizards status` says what is installed and what runs,
|
|
90
91
|
`wizards setup` runs the guided setup again, and `wizards --help` lists the rest.
|
|
91
92
|
|
|
@@ -99,29 +100,30 @@ You need Node.js 24.11 or newer and pnpm 10 (`corepack enable`).
|
|
|
99
100
|
|
|
100
101
|
```bash
|
|
101
102
|
git clone https://github.com/engenty/wizards.git
|
|
102
|
-
cd
|
|
103
|
+
cd wizards
|
|
103
104
|
pnpm install
|
|
104
105
|
pnpm build
|
|
105
106
|
pnpm wizards
|
|
106
107
|
```
|
|
107
108
|
|
|
108
|
-
pnpm may list
|
|
109
|
+
pnpm may list “Ignored build scripts” – that’s expected, nothing to do.
|
|
109
110
|
|
|
110
111
|
Code steps (shell, Node, Python) run in a sandbox when Docker and the sandbox image are on the
|
|
111
112
|
machine; a checkout brings its own sandbox, the installed version has none yet.
|
|
112
113
|
|
|
113
114
|
## First start
|
|
114
115
|
|
|
115
|
-
The setup shows your account at the top and asks
|
|
116
|
-
client that is installed on your computer
|
|
117
|
-
it in for you in a terminal right on the page
|
|
116
|
+
The setup shows your account at the top and asks how the AI should run. Pick an AI
|
|
117
|
+
client that is installed on your computer – engenty uses your existing subscription and signs
|
|
118
|
+
it in for you in a terminal right on the page – your account’s credits, Apple Intelligence on a
|
|
119
|
+
Mac that has it, or your own keys.
|
|
118
120
|
It stays until a test call works, then the studio opens.
|
|
119
121
|
|
|
120
|
-
Change it later under Settings.
|
|
122
|
+
Change it later under Settings → Models.
|
|
121
123
|
|
|
122
124
|
## Using it
|
|
123
125
|
|
|
124
|
-
- **Make a wizard:** describe it in the studio
|
|
126
|
+
- **Make a wizard:** describe it in the studio’s chat, or start from one of the templates.
|
|
125
127
|
You see the steps as a diagram and can change any of them.
|
|
126
128
|
- **Run and share:** try it yourself, then share the link. Shared results are kept for 7 days
|
|
127
129
|
for people without an account.
|
|
@@ -129,8 +131,9 @@ Change it later under Settings.
|
|
|
129
131
|
GitHub, HubSpot and S3 are built in; any other service can be added from its API description
|
|
130
132
|
or MCP server through the [integrations.sh](https://integrations.sh) registry. Services that
|
|
131
133
|
sign in with OAuth need a few settings first: [Connectors](docs/development.md#connectors).
|
|
132
|
-
- **Build from Claude Code or Codex:** Settings →
|
|
133
|
-
|
|
134
|
+
- **Build from Claude Code or Codex:** Settings → Integrate adds engenty wizards to your AI
|
|
135
|
+
apps (Claude Desktop, Claude Code, Codex, Cursor and others), or `wizards connect` from a
|
|
136
|
+
terminal.
|
|
134
137
|
|
|
135
138
|
Your machine only answers on `localhost`. To let others open shared wizards, run it on a server.
|
|
136
139
|
|
|
@@ -149,12 +152,12 @@ Back up the folder; delete it to start over. Settings go into `~/.engenty/wizard
|
|
|
149
152
|
wizards update
|
|
150
153
|
```
|
|
151
154
|
|
|
152
|
-
This runs the installer again without its questions. The studio says
|
|
153
|
-
out and can run the same update from its
|
|
155
|
+
This runs the installer again without its questions. The studio says in a banner at the top
|
|
156
|
+
when a newer release is out and can run the same update from there or from its About dialog.
|
|
154
157
|
From source: `git pull`, `pnpm install`, `pnpm build`. Your data is brought up to date at the
|
|
155
158
|
next start.
|
|
156
159
|
|
|
157
|
-
To remove engenty wizards, run `wizards autostart off`, then delete `~/.engenty/wizards` (your data is in its `data` folder) and
|
|
160
|
+
To remove engenty wizards, run `wizards stop`, `wizards autostart off` and `wizards disconnect`, then delete `~/.engenty/wizards` (your data is in its `data` folder) and
|
|
158
161
|
`~/.local/bin/wizards`.
|
|
159
162
|
|
|
160
163
|
## Run it on a server
|
|
@@ -163,24 +166,24 @@ With Docker, behind an https proxy (Caddy, Traefik, Coolify):
|
|
|
163
166
|
|
|
164
167
|
```bash
|
|
165
168
|
git clone https://github.com/engenty/wizards.git
|
|
166
|
-
cd
|
|
169
|
+
cd wizards
|
|
167
170
|
cp .env.example .env # set APP_URL to your https address and add a model key
|
|
168
171
|
docker compose up -d --build
|
|
169
172
|
docker compose logs # shows the link to open once
|
|
170
173
|
```
|
|
171
174
|
|
|
172
|
-
Point the proxy at port 8891. On a server, engenty
|
|
173
|
-
AI clients
|
|
175
|
+
Point the proxy at port 8891. On a server, engenty uses your keys or Ollama; the
|
|
176
|
+
AI clients’ subscriptions live on your own computer. The code sandbox is off in this image.
|
|
174
177
|
|
|
175
178
|
## Troubleshooting
|
|
176
179
|
|
|
177
180
|
| | |
|
|
178
181
|
|---|---|
|
|
179
|
-
|
|
|
182
|
+
| “This link is no longer valid” | The link works once. `wizards open` gives this browser a new one. |
|
|
180
183
|
| `wizards`: command not found | Open a new terminal, or run `~/.local/bin/wizards`. |
|
|
181
184
|
| You open it under another address | Set `APP_URL` in `~/.engenty/wizards/.env` to the address you open. |
|
|
182
|
-
| An AI client shows as not signed in | Sign it in on the setup page, or in your own terminal (e.g. `claude`, `codex login`), then
|
|
183
|
-
| PDF or PNG export fails | Install
|
|
185
|
+
| An AI client shows as not signed in | Sign it in on the setup page, or in your own terminal (e.g. `claude`, `codex login`), then “Check again”. |
|
|
186
|
+
| PDF or PNG export fails | Install Chrome, Edge or Chromium (on a Mac also Brave), or set `CHROME_PATH` to one. |
|
|
184
187
|
| Port 24368 is taken | The next free port is used. To fix one, set `API_PORT` in `~/.engenty/wizards/.env`. |
|
|
185
188
|
| Something else | `wizards doctor` checks the install. |
|
|
186
189
|
|
|
@@ -194,12 +197,12 @@ Development server, checks, how it is built, the managed mode:
|
|
|
194
197
|
Plugins add tools for steps, routes with their own tables and pages in the studio, without
|
|
195
198
|
changing the runtime: [docs/content/dev/plugins](docs/content/dev/plugins/index.md).
|
|
196
199
|
|
|
197
|
-
The documentation
|
|
200
|
+
The documentation – a user guide and the developer docs – is in [docs/content](docs/content)
|
|
198
201
|
and is a site of its own: `pnpm dev:docs`.
|
|
199
202
|
|
|
200
203
|
## License
|
|
201
204
|
|
|
202
|
-
[FSL-1.1-MIT](LICENSE): use it for yourself and your company, run it, change it
|
|
205
|
+
[FSL-1.1-MIT](LICENSE): use it for yourself and your company, run it, change it – just don’t
|
|
203
206
|
offer it to others as a competing product or service. Each release becomes MIT two years
|
|
204
207
|
after it is published. [COPYRIGHTS.md](COPYRIGHTS.md) names the owner, the marks, what is not ours and the
|
|
205
208
|
third-party software with its licences.
|
|
@@ -42,9 +42,9 @@ THE PAGE
|
|
|
42
42
|
- fill_field never saves: say that the person checks and saves. You never press buttons for the person.
|
|
43
43
|
|
|
44
44
|
THE SPACE
|
|
45
|
-
- Where a space's tools are there, you also fill the space in: what every wizard of the space draws on — who they are (title, about), the brand (logos, colours), assets (images, graphics, videos), documents, and facts (label → value: address, VAT
|
|
46
|
-
- A website: read_website it first. You get the page's text, colours from its stylesheet, logo candidates and the links to imprint / contact / about. Read those pages too (at most four more) for address, VAT
|
|
47
|
-
- Facts: one fact per thing, a short label in the person's language ("Adresse", "
|
|
45
|
+
- Where a space's tools are there, you also fill the space in: what every wizard of the space draws on — who they are (title, about), the brand (logos, colours), assets (images, graphics, videos), documents, and facts (label → value: address, VAT ID, phone, opening hours — anything). The space as it is now comes with every message then; you change it ONLY through tools.
|
|
46
|
+
- A website: read_website it first. You get the page's text, colours from its stylesheet, logo candidates and the links to imprint / contact / about. Read those pages too (at most four more) for address, VAT ID, register number, phone, email, bank details, who runs it.
|
|
47
|
+
- Facts: one fact per thing, a short label in the person's language ("Adresse", "USt-IdNr.", "Telefon"), the value on one line where it fits. Only what a source or the person states — never guess, never invent. Keep the facts that are there; a fact with a known label is updated.
|
|
48
48
|
- About: two to five sentences — what they do, for whom, what sets them apart, the tone they write in. Rewrite it only when you learned something new or the person asks.
|
|
49
49
|
- Colours: two to six, the main one first, each with a name that says what it is for ("Primär", "Hintergrund", "Text"). Take them from the stylesheet's variables or its most used colours, never from photos. set_colors replaces the list: pass all colours that should remain. Colours in no section are the standard ones; the first of them is the accent. Colour sections are optional like logo sections: only for a further palette a brand guide or the person names for its own use ("Illustration – drawings and charts"), never for the standard colours. A brand's gradients (set_gradients, as CSS) only where a brand guide or the site's stylesheet has them; patterns and background fills are pictures the person uploads.
|
|
50
50
|
- Logos: save the best candidate (an SVG or a large PNG rather than a favicon); a second one only if it truly differs (for dark ground, a signet). A few images that show the business (header, team, products) may be saved as assets — a handful, never everything.
|
package/apps/runtime/dist/app.js
CHANGED
|
@@ -23,7 +23,7 @@ import { PLUGIN_NAME, pluginArchive, pluginMarketplace } from "./plugin.js";
|
|
|
23
23
|
import { apiRoutes } from "./routes/api.js";
|
|
24
24
|
import { browserReport, localDebugRoutes } from "./routes/debug.js";
|
|
25
25
|
import { internalRoutes } from "./routes/internal.js";
|
|
26
|
-
import { inLang, requestLang } from "./routes/lang.js";
|
|
26
|
+
import { inLang, notFoundAnswer, requestLang } from "./routes/lang.js";
|
|
27
27
|
import { marketplaceStudio } from "./routes/marketplace.js";
|
|
28
28
|
import { publicPluginRoutes } from "./routes/plugin-public.js";
|
|
29
29
|
import { pluginRoutes } from "./routes/plugins.js";
|
|
@@ -67,7 +67,7 @@ const ticketedRun = /^\/api\/runs\/([^/]+)(\/|$)/;
|
|
|
67
67
|
app.use("*", async (c, next) => {
|
|
68
68
|
if (!managed && !hostAllowed(c.req.header("host") ?? new URL(c.req.url).host)) {
|
|
69
69
|
// Says where it does answer: the studio opened under another name shows the way there.
|
|
70
|
-
return c.json({ error: "
|
|
70
|
+
return c.json({ error: "This address isn’t allowed.", code: "host", appUrl: env.appUrl }, 403);
|
|
71
71
|
}
|
|
72
72
|
const origin = c.req.header("origin");
|
|
73
73
|
const path = c.req.path.startsWith(`${basePath}/`)
|
|
@@ -201,7 +201,10 @@ if (serves.studio) {
|
|
|
201
201
|
app.use("/api/studio/*", async (c, next) => {
|
|
202
202
|
const user = await principalOf(c);
|
|
203
203
|
if (!user) {
|
|
204
|
-
return c.json({
|
|
204
|
+
return c.json({
|
|
205
|
+
error: inLang(c, "Du bist nicht angemeldet.", "You’re not signed in."),
|
|
206
|
+
code: "unauthorized",
|
|
207
|
+
}, 401);
|
|
205
208
|
}
|
|
206
209
|
if ((await tenantStatus(user.tenantId)) === "suspended") {
|
|
207
210
|
return c.json({
|
|
@@ -257,7 +260,7 @@ if (serves.studio) {
|
|
|
257
260
|
return c.body(new Uint8Array(zip), 200, { "content-type": "application/zip" });
|
|
258
261
|
});
|
|
259
262
|
}
|
|
260
|
-
app.all("/api/*", (c) => c.json(
|
|
263
|
+
app.all("/api/*", (c) => c.json(notFoundAnswer(c), 404));
|
|
261
264
|
/**
|
|
262
265
|
* `/w/<token>/<runner>`: a plugin's page runner, where the tenant has it and the wizard offers
|
|
263
266
|
* it; otherwise the next handler (the app's page, which knows `steps`, `chat` and run ids).
|
|
@@ -184,7 +184,7 @@ export const authRoutes = new Hono()
|
|
|
184
184
|
usedTickets.set(ticket, expires);
|
|
185
185
|
}
|
|
186
186
|
else if (managed || !accessKey || !sameValue(given, accessKey)) {
|
|
187
|
-
return c.text("This link is no longer valid.
|
|
187
|
+
return c.text("This link is no longer valid. Run wizards open to get a new one.", 403);
|
|
188
188
|
}
|
|
189
189
|
else {
|
|
190
190
|
accessKey = null;
|
|
@@ -285,7 +285,7 @@ export const authRoutes = new Hono()
|
|
|
285
285
|
}
|
|
286
286
|
catch (err) {
|
|
287
287
|
console.error("[account]", err);
|
|
288
|
-
return c.html(closePage("The sign-in
|
|
288
|
+
return c.html(closePage("The sign-in didn’t work. Try again."), 400);
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
const state = unseal(getCookie(c, STATE_COOKIE) ?? "");
|
|
@@ -243,7 +243,7 @@ type ResultStep = { type: "result", message?: string, deliverables: { from: step
|
|
|
243
243
|
|
|
244
244
|
Templates (in instructions/prompt): {{fieldId}} · {{steps.stepId}} (whole output) · {{steps.stepId.key}} (json key)
|
|
245
245
|
· {{itemsField}} (line items as a table WITH computed net/VAT/total) · {{itemsField.net|vat|gross}} · {{today}}
|
|
246
|
-
· the project (its settings): {{brand.name}} {{brand.about}} {{brand.colors}} · {{facts.key}} (one fact: address, VAT
|
|
246
|
+
· the project (its settings): {{brand.name}} {{brand.about}} {{brand.colors}} · {{facts.key}} (one fact: address, VAT ID, …) · {{facts}} (all facts)
|
|
247
247
|
— every AI step already knows them, name one only where the text must carry it; agent steps also search the space's Knowledge
|
|
248
248
|
and are told its categories: say in a step's instructions which category to filter by when the task names one
|
|
249
249
|
· {{lists.listId}} (the stored list as a table, as it is when the step starts) · {{fileField}} (the names of the uploads, for read_document)
|
|
@@ -4,9 +4,9 @@ import { DeviceSignInError, requestDeviceCode, waitForDeviceSignIn } from "../au
|
|
|
4
4
|
import { migrateControlDb } from "../db/client.js";
|
|
5
5
|
import { env } from "../env.js";
|
|
6
6
|
import { featuresFile, fileFeatures, writeFeature } from "../features.js";
|
|
7
|
-
import {
|
|
7
|
+
import { readInstallNote, writeInstallNote } from "./home.js";
|
|
8
8
|
import { openBrowser, runningRuntime, settings } from "./start.js";
|
|
9
|
-
import { bold, busy, cyan, dim, tilde } from "./ui.js";
|
|
9
|
+
import { bold, busy, cmd, cyan, dim, tilde } from "./ui.js";
|
|
10
10
|
/**
|
|
11
11
|
* The account of this install, from the terminal. `wizards account` says where it stands,
|
|
12
12
|
* `sign-in` runs the device flow (auth/device.ts), `sign-out` ends the link the way the
|
|
@@ -73,7 +73,7 @@ export function described(account, team, credits = true) {
|
|
|
73
73
|
export function describeAccount(state) {
|
|
74
74
|
switch (state.kind) {
|
|
75
75
|
case "local":
|
|
76
|
-
return "
|
|
76
|
+
return "only on this computer, no account";
|
|
77
77
|
case "none":
|
|
78
78
|
return "not signed in";
|
|
79
79
|
default:
|
|
@@ -86,16 +86,18 @@ const host = () => new URL(env.local.accountUrl).host.replace(/^account\./, "");
|
|
|
86
86
|
async function status() {
|
|
87
87
|
const state = await accountState();
|
|
88
88
|
if (state.kind === "local") {
|
|
89
|
-
console.log(`
|
|
89
|
+
console.log(`Only on this computer, no account. ${dim(`To connect one: ${cmd("account sign-in")}`)}`);
|
|
90
90
|
return 0;
|
|
91
91
|
}
|
|
92
92
|
if (state.kind === "none") {
|
|
93
|
-
console.log(`Not signed in. ${dim(
|
|
93
|
+
console.log(`Not signed in. ${dim(`To sign in: ${cmd("account sign-in")}`)}`);
|
|
94
94
|
return 0;
|
|
95
95
|
}
|
|
96
96
|
const overview = await accountOverview();
|
|
97
97
|
const team = overview?.tenant ?? state.team;
|
|
98
|
-
console.log(`Signed in as ${described(state.account, team)} · ${host()}${overview
|
|
98
|
+
console.log(`Signed in as ${described(state.account, team)} · ${host()}${overview
|
|
99
|
+
? ""
|
|
100
|
+
: dim(` (${host()} didn’t respond${team ? ", so this is from last time" : ""})`)}`);
|
|
99
101
|
return 0;
|
|
100
102
|
}
|
|
101
103
|
/**
|
|
@@ -112,21 +114,21 @@ async function deviceSignIn() {
|
|
|
112
114
|
return null;
|
|
113
115
|
}
|
|
114
116
|
const link = code.verificationUriComplete ?? code.verificationUri;
|
|
115
|
-
p.log.message(`Open ${cyan(link)} and
|
|
117
|
+
p.log.message(`Open ${cyan(link)} and enter the code ${bold(code.userCode)}.`);
|
|
116
118
|
if (openBrowser(link)) {
|
|
117
119
|
p.log.message(dim("The page opens in your browser."));
|
|
118
120
|
}
|
|
119
|
-
const spinner = busy("Waiting for you to
|
|
121
|
+
const spinner = busy("Waiting for you to confirm in the browser…");
|
|
120
122
|
try {
|
|
121
123
|
const account = await waitForDeviceSignIn(code);
|
|
122
124
|
const overview = await accountOverview();
|
|
123
|
-
spinner.stop(`Signed in as ${described(account, overview?.tenant ?? null)}
|
|
125
|
+
spinner.stop(`Signed in as ${described(account, overview?.tenant ?? null)}.`);
|
|
124
126
|
return account;
|
|
125
127
|
}
|
|
126
128
|
catch (err) {
|
|
127
129
|
spinner.fail(err instanceof DeviceSignInError
|
|
128
130
|
? err.message
|
|
129
|
-
: `The sign-in
|
|
131
|
+
: `The sign-in didn’t work. ${err.message}`);
|
|
130
132
|
return null;
|
|
131
133
|
}
|
|
132
134
|
}
|
|
@@ -139,29 +141,28 @@ async function pickUp(paths, interactive, why) {
|
|
|
139
141
|
if (!(await runningRuntime(settings(paths).dataDir))) {
|
|
140
142
|
return;
|
|
141
143
|
}
|
|
142
|
-
const how = `${command()} restart`;
|
|
143
144
|
if (!interactive) {
|
|
144
|
-
p.log.info(`
|
|
145
|
+
p.log.info(`Run ${cmd("restart")} so ${why}.`);
|
|
145
146
|
return;
|
|
146
147
|
}
|
|
147
148
|
const answer = await p.confirm({
|
|
148
|
-
message: `Restart
|
|
149
|
+
message: `Restart engenty wizards now, so ${why}?`,
|
|
149
150
|
initialValue: true,
|
|
150
151
|
});
|
|
151
152
|
if (p.isCancel(answer) || !answer) {
|
|
152
|
-
p.log.info(dim(`
|
|
153
|
+
p.log.info(dim(`To do it later: ${cmd("restart")}`));
|
|
153
154
|
return;
|
|
154
155
|
}
|
|
155
156
|
// status.ts shows the account; loaded here when needed, so neither module waits on the other.
|
|
156
157
|
const { restart } = await import("./status.js");
|
|
157
158
|
await restart(paths);
|
|
158
159
|
}
|
|
159
|
-
const SIGNED_IN = "
|
|
160
|
+
const SIGNED_IN = "your plan’s Pro modules load and your published wizards arrive in the cloud";
|
|
160
161
|
async function signIn(paths, interactive) {
|
|
161
162
|
await ready();
|
|
162
163
|
const linked = await linkedAccount();
|
|
163
164
|
if (linked) {
|
|
164
|
-
p.log.info(`Already signed in as ${described(linked, await knownTeam(), false)}. ${dim(`To switch
|
|
165
|
+
p.log.info(`Already signed in as ${described(linked, await knownTeam(), false)}. ${dim(`To switch accounts, run ${cmd("account sign-out")} first.`)}`);
|
|
165
166
|
return 0;
|
|
166
167
|
}
|
|
167
168
|
const account = await deviceSignIn();
|
|
@@ -176,10 +177,12 @@ async function signIn(paths, interactive) {
|
|
|
176
177
|
async function signOut(paths, interactive) {
|
|
177
178
|
const state = await accountState();
|
|
178
179
|
if (state.kind !== "linked") {
|
|
179
|
-
console.log(state.kind === "local"
|
|
180
|
+
console.log(state.kind === "local"
|
|
181
|
+
? "No account is connected, so there’s nothing to sign out of."
|
|
182
|
+
: "Not signed in.");
|
|
180
183
|
return 0;
|
|
181
184
|
}
|
|
182
|
-
const spinner = busy(`Signing out ${state.account.name || state.account.email}
|
|
185
|
+
const spinner = busy(`Signing out ${state.account.name || state.account.email}…`);
|
|
183
186
|
await unlink();
|
|
184
187
|
// The same as the studio's sign-out (DELETE /api/studio/account): what was sent to the cloud
|
|
185
188
|
// is forgotten, the entitlement goes with the account's plan, and models that ran on its
|
|
@@ -197,7 +200,7 @@ async function signOut(paths, interactive) {
|
|
|
197
200
|
await models.saveLocalModels({ source: "own" });
|
|
198
201
|
}
|
|
199
202
|
spinner.stop("Signed out. Your wizards and results stay on this computer.");
|
|
200
|
-
await pickUp(paths, interactive, "
|
|
203
|
+
await pickUp(paths, interactive, "it disconnects from the account");
|
|
201
204
|
return 0;
|
|
202
205
|
}
|
|
203
206
|
/** `wizards account [sign-in|sign-out]`. */
|
|
@@ -215,7 +218,7 @@ export async function accountCommand(paths, value, options) {
|
|
|
215
218
|
case "logout":
|
|
216
219
|
return signOut(paths, interactive);
|
|
217
220
|
default:
|
|
218
|
-
console.error(
|
|
221
|
+
console.error(`Usage: ${cmd("account [sign-in|sign-out]")}`);
|
|
219
222
|
return 2;
|
|
220
223
|
}
|
|
221
224
|
}
|
|
@@ -250,37 +253,37 @@ export async function accountMenu(paths) {
|
|
|
250
253
|
export async function accountStep(paths, options, interactive) {
|
|
251
254
|
if (options.local) {
|
|
252
255
|
localOnly(paths);
|
|
253
|
-
p.log.warn(`
|
|
254
|
-
p.log.message(dim(`
|
|
256
|
+
p.log.warn(`No account: nothing leaves this computer. Your wizards, your space and results stay in ${tilde(settings(paths).dataDir)}. Links work only on this computer.`);
|
|
257
|
+
p.log.message(dim(`To connect an account any time: ${cmd("account sign-in")}`));
|
|
255
258
|
return;
|
|
256
259
|
}
|
|
257
260
|
const state = await accountState();
|
|
258
261
|
if (state.kind === "local") {
|
|
259
|
-
p.log.info(`
|
|
262
|
+
p.log.info(`Only on this computer, no account. ${dim(`To connect one: ${cmd("account sign-in")}`)}`);
|
|
260
263
|
return;
|
|
261
264
|
}
|
|
262
265
|
if (state.kind === "linked") {
|
|
263
266
|
const overview = await accountOverview();
|
|
264
|
-
p.log.success(`Signed in as ${described(state.account, overview?.tenant ?? state.team)}
|
|
267
|
+
p.log.success(`Signed in as ${described(state.account, overview?.tenant ?? state.team)}.`);
|
|
265
268
|
return;
|
|
266
269
|
}
|
|
267
270
|
p.note(INTRO, "Your engenty account");
|
|
268
271
|
if (!interactive) {
|
|
269
|
-
p.log.info(dim(`
|
|
272
|
+
p.log.info(dim(`To sign in later: ${cmd("account sign-in")}`));
|
|
270
273
|
return;
|
|
271
274
|
}
|
|
272
275
|
const answer = await p.confirm({ message: "Sign in now?", initialValue: true });
|
|
273
276
|
if (p.isCancel(answer)) {
|
|
274
|
-
p.cancel(`Setup stopped.
|
|
277
|
+
p.cancel(`Setup stopped. To run it again: ${cmd("setup")}`);
|
|
275
278
|
return "cancelled";
|
|
276
279
|
}
|
|
277
280
|
if (!answer) {
|
|
278
|
-
p.log.info(dim(`
|
|
281
|
+
p.log.info(dim(`To sign in later: ${cmd("account sign-in")}`));
|
|
279
282
|
return;
|
|
280
283
|
}
|
|
281
284
|
const account = await deviceSignIn();
|
|
282
285
|
if (!account) {
|
|
283
|
-
p.log.info(dim(`
|
|
286
|
+
p.log.info(dim(`To sign in later: ${cmd("account sign-in")}`));
|
|
284
287
|
return;
|
|
285
288
|
}
|
|
286
289
|
joinedAccount(paths);
|
|
@@ -82,16 +82,18 @@ async function systemdHere() {
|
|
|
82
82
|
}
|
|
83
83
|
export async function autostartState(paths) {
|
|
84
84
|
if (process.platform !== "darwin" && process.platform !== "linux") {
|
|
85
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
unavailable: process.platform === "win32" ? "not on Windows" : `not on ${process.platform}`,
|
|
87
|
+
};
|
|
86
88
|
}
|
|
87
89
|
if (!installedByScript(paths)) {
|
|
88
|
-
return { unavailable: "only for
|
|
90
|
+
return { unavailable: "only for installs made with the install script" };
|
|
89
91
|
}
|
|
90
92
|
if (process.platform === "darwin") {
|
|
91
93
|
return { on: existsSync(LOGIN_ITEM), how: MAC_HOW };
|
|
92
94
|
}
|
|
93
95
|
if (!(await systemdHere())) {
|
|
94
|
-
return { unavailable: "this
|
|
96
|
+
return { unavailable: "this system has no systemd user session" };
|
|
95
97
|
}
|
|
96
98
|
try {
|
|
97
99
|
await run("systemctl", ["--user", "is-enabled", "--quiet", UNIT], { timeout: 10_000 });
|
|
@@ -28,7 +28,7 @@ export function installClient(client, paths, onLine) {
|
|
|
28
28
|
}
|
|
29
29
|
const npm = findOnPath("npm", [dirname(process.execPath), process.env.PATH ?? ""].join(delimiter));
|
|
30
30
|
if (!npm) {
|
|
31
|
-
return Promise.resolve({ code: 127, tail: "npm
|
|
31
|
+
return Promise.resolve({ code: 127, tail: "npm wasn’t found next to this Node.js." });
|
|
32
32
|
}
|
|
33
33
|
mkdirSync(paths.clients, { recursive: true });
|
|
34
34
|
return runLogged(npm, [
|