wizards 0.5.0 → 0.5.2

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 (160) hide show
  1. package/README.md +45 -42
  2. package/apps/runtime/dist/agents/studio-assistant.js +3 -3
  3. package/apps/runtime/dist/app.js +7 -4
  4. package/apps/runtime/dist/auth/index.js +2 -2
  5. package/apps/runtime/dist/authoring/guide.js +1 -1
  6. package/apps/runtime/dist/cli/account.js +31 -28
  7. package/apps/runtime/dist/cli/autostart.js +5 -3
  8. package/apps/runtime/dist/cli/clients.js +1 -1
  9. package/apps/runtime/dist/cli/connect.js +24 -24
  10. package/apps/runtime/dist/cli/features.js +6 -6
  11. package/apps/runtime/dist/cli/main.js +51 -39
  12. package/apps/runtime/dist/cli/mcp.js +5 -4
  13. package/apps/runtime/dist/cli/menu.js +32 -30
  14. package/apps/runtime/dist/cli/report.js +7 -9
  15. package/apps/runtime/dist/cli/setup.js +42 -38
  16. package/apps/runtime/dist/cli/start.js +16 -15
  17. package/apps/runtime/dist/cli/status.js +20 -20
  18. package/apps/runtime/dist/cli/ui.js +9 -2
  19. package/apps/runtime/dist/cli/update.js +6 -6
  20. package/apps/runtime/dist/cli/validate.js +1 -1
  21. package/apps/runtime/dist/connectors/external.js +3 -2
  22. package/apps/runtime/dist/connectors/index.js +5 -5
  23. package/apps/runtime/dist/connectors/plugin-connections.js +2 -2
  24. package/apps/runtime/dist/connectors/via-account.js +5 -5
  25. package/apps/runtime/dist/db/control-schema.js +14 -0
  26. package/apps/runtime/dist/db/migrations/control/0009_plugin_claim.sql +9 -0
  27. package/apps/runtime/dist/db/migrations/control/meta/0009_snapshot.json +561 -0
  28. package/apps/runtime/dist/db/migrations/control/meta/_journal.json +7 -0
  29. package/apps/runtime/dist/docs/dev/index.md +16 -14
  30. package/apps/runtime/dist/docs/dev/plugins/connections.md +27 -24
  31. package/apps/runtime/dist/docs/dev/plugins/events.md +19 -17
  32. package/apps/runtime/dist/docs/dev/plugins/examples.md +13 -12
  33. package/apps/runtime/dist/docs/dev/plugins/index.md +29 -24
  34. package/apps/runtime/dist/docs/dev/plugins/layout.md +20 -19
  35. package/apps/runtime/dist/docs/dev/plugins/quick-start.md +16 -15
  36. package/apps/runtime/dist/docs/dev/plugins/reference.md +52 -40
  37. package/apps/runtime/dist/docs/dev/plugins/reloading.md +24 -23
  38. package/apps/runtime/dist/docs/dev/plugins/routes.md +26 -22
  39. package/apps/runtime/dist/docs/dev/plugins/runners.md +49 -44
  40. package/apps/runtime/dist/docs/dev/plugins/server.md +95 -43
  41. package/apps/runtime/dist/docs/dev/plugins/shipping.md +19 -16
  42. package/apps/runtime/dist/docs/dev/plugins/space.md +75 -69
  43. package/apps/runtime/dist/docs/dev/plugins/starters.md +22 -17
  44. package/apps/runtime/dist/docs/dev/plugins/studio.md +80 -37
  45. package/apps/runtime/dist/docs/dev/plugins/styling.md +44 -41
  46. package/apps/runtime/dist/docs/dev/plugins/tables.md +11 -11
  47. package/apps/runtime/dist/docs/dev/plugins/tools.md +26 -25
  48. package/apps/runtime/dist/docs/dev/wizard-format.md +35 -23
  49. package/apps/runtime/dist/docs/user/ai-apps.md +46 -43
  50. package/apps/runtime/dist/docs/user/assistant.md +41 -36
  51. package/apps/runtime/dist/docs/user/build-a-wizard.md +64 -39
  52. package/apps/runtime/dist/docs/user/command-line.md +47 -44
  53. package/apps/runtime/dist/docs/user/connectors.md +40 -35
  54. package/apps/runtime/dist/docs/user/create-account.md +27 -22
  55. package/apps/runtime/dist/docs/user/data.md +29 -29
  56. package/apps/runtime/dist/docs/user/first-start.md +26 -28
  57. package/apps/runtime/dist/docs/user/index.md +16 -17
  58. package/apps/runtime/dist/docs/user/install.md +28 -27
  59. package/apps/runtime/dist/docs/user/local-only.md +21 -17
  60. package/apps/runtime/dist/docs/user/models.md +92 -84
  61. package/apps/runtime/dist/docs/user/plugins.md +28 -23
  62. package/apps/runtime/dist/docs/user/run.md +51 -50
  63. package/apps/runtime/dist/docs/user/server.md +9 -9
  64. package/apps/runtime/dist/docs/user/space.md +87 -65
  65. package/apps/runtime/dist/docs/user/steps.md +73 -69
  66. package/apps/runtime/dist/docs/user/test-and-share.md +127 -105
  67. package/apps/runtime/dist/docs/user/troubleshooting.md +40 -38
  68. package/apps/runtime/dist/docs/user/wordpress.md +62 -54
  69. package/apps/runtime/dist/documents/parse.js +2 -2
  70. package/apps/runtime/dist/engenty/shims/web-ingest.js +17 -1
  71. package/apps/runtime/dist/engine/input.js +4 -4
  72. package/apps/runtime/dist/engine/push.js +2 -2
  73. package/apps/runtime/dist/engine/runner.js +8 -8
  74. package/apps/runtime/dist/engine/steps.js +2 -2
  75. package/apps/runtime/dist/engine/surface.js +1 -1
  76. package/apps/runtime/dist/film/step.js +3 -3
  77. package/apps/runtime/dist/harness/claude.js +1 -1
  78. package/apps/runtime/dist/harness/codex.js +1 -1
  79. package/apps/runtime/dist/harness/model.js +2 -2
  80. package/apps/runtime/dist/harness/terminal.js +3 -3
  81. package/apps/runtime/dist/mcp/handler.js +2 -2
  82. package/apps/runtime/dist/mcp/tools.js +9 -9
  83. package/apps/runtime/dist/models.js +15 -15
  84. package/apps/runtime/dist/plugins/claims.js +56 -0
  85. package/apps/runtime/dist/plugins/loader.js +2 -0
  86. package/apps/runtime/dist/plugins/public.js +2 -3
  87. package/apps/runtime/dist/plugins/runs.js +13 -8
  88. package/apps/runtime/dist/render/chromium.js +24 -11
  89. package/apps/runtime/dist/routes/api.js +15 -9
  90. package/apps/runtime/dist/routes/debug.js +1 -1
  91. package/apps/runtime/dist/routes/delivery.js +46 -0
  92. package/apps/runtime/dist/routes/lang.js +7 -0
  93. package/apps/runtime/dist/routes/marketplace.js +2 -1
  94. package/apps/runtime/dist/routes/plugin-public.js +2 -1
  95. package/apps/runtime/dist/routes/plugins.js +13 -14
  96. package/apps/runtime/dist/routes/runs.js +59 -49
  97. package/apps/runtime/dist/routes/studio.js +53 -23
  98. package/apps/runtime/dist/services/access.js +3 -3
  99. package/apps/runtime/dist/services/assistant-chats.js +1 -1
  100. package/apps/runtime/dist/services/brand.js +2 -2
  101. package/apps/runtime/dist/services/cloud.js +5 -4
  102. package/apps/runtime/dist/services/errors.js +2 -1
  103. package/apps/runtime/dist/services/knowledge-model.js +2 -2
  104. package/apps/runtime/dist/services/marketplace.js +2 -2
  105. package/apps/runtime/dist/services/package-file.js +12 -9
  106. package/apps/runtime/dist/services/package.js +2 -2
  107. package/apps/runtime/dist/services/project-files.js +10 -12
  108. package/apps/runtime/dist/services/projects.js +13 -8
  109. package/apps/runtime/dist/services/runners.js +4 -3
  110. package/apps/runtime/dist/services/runs.js +3 -3
  111. package/apps/runtime/dist/services/site.js +2 -2
  112. package/apps/runtime/dist/services/space-categories.js +4 -4
  113. package/apps/runtime/dist/services/space-data.js +13 -13
  114. package/apps/runtime/dist/services/space-origin.js +1 -1
  115. package/apps/runtime/dist/services/spaces.js +7 -7
  116. package/apps/runtime/dist/services/wizards.js +5 -5
  117. package/apps/runtime/dist/tools/net-guard.js +135 -24
  118. package/apps/runtime/dist/tools/plugin.js +1 -1
  119. package/apps/runtime/dist/tools/store.js +1 -1
  120. package/apps/runtime/dist/widgets/step.js +1 -1
  121. package/apps/web/dist/assets/AboutDialog-hRgrS60N.js +1 -0
  122. package/apps/web/dist/assets/{ChangelogDialog-BXpkgatF.js → ChangelogDialog-BUSpLhC6.js} +1 -1
  123. package/apps/web/dist/assets/{ChatView-t7z44uFN.js → ChatView-DO7P5Vv_.js} +1 -1
  124. package/apps/web/dist/assets/EditorPage-BabV35Bj.js +3 -0
  125. package/apps/web/dist/assets/{FlowPreview-WpS8DCPl.js → FlowPreview-CKrwLPN0.js} +1 -1
  126. package/apps/web/dist/assets/{Harness-DL7Bse40.js → Harness-o8IIQXZp.js} +1 -1
  127. package/apps/web/dist/assets/{NewWizardChannels-Crt6PzH2.js → NewWizardChannels-DqU79Myj.js} +1 -1
  128. package/apps/web/dist/assets/{NewWizardPage-COiVmNsl.js → NewWizardPage-D1UCvmDp.js} +1 -1
  129. package/apps/web/dist/assets/{OnboardingPage-BwluEqXq.js → OnboardingPage-C70bqPnq.js} +1 -1
  130. package/apps/web/dist/assets/{ProjectPage-BIRU_AlN.js → ProjectPage-BOLvmQWZ.js} +1 -1
  131. package/apps/web/dist/assets/{PublicRunner-BxMb4gEt.js → PublicRunner-B0PGyHI9.js} +1 -1
  132. package/apps/web/dist/assets/{ReadOnly-D9r5ze5S.js → ReadOnly-B0mJBD1q.js} +1 -1
  133. package/apps/web/dist/assets/{RunDrawer-DmJl2QOJ.js → RunDrawer-BsnsIJ0Y.js} +1 -1
  134. package/apps/web/dist/assets/{RunnerView-CF_1rC-7.js → RunnerView-B56i3nKO.js} +1 -1
  135. package/apps/web/dist/assets/SettingsPage-BvfRUqb2.js +1 -0
  136. package/apps/web/dist/assets/{SetupPage-BGKtbS7j.js → SetupPage-BvAFPu1J.js} +1 -1
  137. package/apps/web/dist/assets/{SharePage-C4MqXKDA.js → SharePage-hV5pYrO2.js} +1 -1
  138. package/apps/web/dist/assets/changelog-BftXQzUA.js +1 -0
  139. package/apps/web/dist/assets/{esm-CsY8TkyE.js → esm-DfapVSy6.js} +1 -1
  140. package/apps/web/dist/assets/{index-BjQvGQp_.js → index-BuFrRzvG.js} +4 -4
  141. package/apps/web/dist/assets/{index-Bi2x2g7n.css → index-DSbQiZY8.css} +1 -1
  142. package/apps/web/dist/assets/{lock-CI6TpWL-.js → lock-B-tJwE4p.js} +1 -1
  143. package/apps/web/dist/assets/oss-credits-BJrR7BR1.js +1 -0
  144. package/apps/web/dist/assets/{phone-BrtQz-fG.js → phone-DRHxY0l_.js} +1 -1
  145. package/apps/web/dist/assets/{settings-menu-BtEKL72n.js → settings-menu-OPrJTW8a.js} +1 -1
  146. package/apps/web/dist/assets/{ui-4IaTD7LB.js → ui-DftgEA2k.js} +3 -3
  147. package/apps/web/dist/assets/{upload-CWJAtPRo.js → upload-B73coFNw.js} +1 -1
  148. package/apps/web/dist/index.html +3 -3
  149. package/apps/web/dist/mcp/flow.html +4 -4
  150. package/bin/wizards.mjs +1 -1
  151. package/node_modules/@engenty-wizards/plugin-sdk/dist/index.d.ts +21 -2
  152. package/node_modules/@engenty-wizards/shared/dist/projects.js +1 -1
  153. package/node_modules/@engenty-wizards/shared/dist/run.d.ts +48 -48
  154. package/node_modules/@engenty-wizards/shared/dist/run.js +48 -48
  155. package/package.json +5 -4
  156. package/apps/web/dist/assets/AboutDialog-A_ILyeue.js +0 -1
  157. package/apps/web/dist/assets/EditorPage-4qxNJgKr.js +0 -3
  158. package/apps/web/dist/assets/SettingsPage-3xSInE-A.js +0 -1
  159. package/apps/web/dist/assets/changelog-CM_GdIVI.js +0 -1
  160. package/apps/web/dist/assets/oss-credits-BQQX0kvk.js +0 -1
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  title: Accounts
3
- description: Accounts a plugin connects for a space — a calendar, a mailbox — through the runtime's built-in connectors.
4
- version: 0.3.2
3
+ description: Accounts a plugin connects for a space, such as a calendar or a mailbox, through the runtime's built-in connectors.
4
+ version: 0.5.0
5
5
  ---
6
6
 
7
- A wizard's connections belong to the person who runs it. A plugin that works for the whole
8
- space, a calendar that every booking wizard reads, connects an account of its own:
9
- `server.connections`. It uses the runtime's built-in OAuth connectors (Google, Microsoft, Slack,
10
- GitHub, HubSpot …), keeps the tokens sealed in the tenant's database, and refreshes them.
7
+ A wizard’s connections belong to the person who runs it. A plugin that works for the whole
8
+ space, such as a calendar that every booking wizard reads, connects an account of its own with
9
+ `server.connections`. It uses the runtime’s built-in connectors (Google, Microsoft, Slack,
10
+ GitHub, HubSpot, S3 …). The runtime keeps the tokens and keys sealed in the tenant’s database and
11
+ refreshes the tokens.
11
12
 
12
13
  ```ts
13
14
  const ACTIONS = ["list_events", "create_event", "delete_event"];
@@ -28,44 +29,46 @@ const { events } = await server.connections.call<{ events: unknown[] }>(account.
28
29
 
29
30
  | `server.connections.` | Does |
30
31
  |---|---|
31
- | `available(ids)` | Of these connector ids, the ones a person can connect here now: `{ id, name, auth }`, and for `auth: "api_key"` the `fields` to ask for (`key`, `label`, `placeholder`, `required`, `secret`). An OAuth connector is offered once its client is set up (`GOOGLE_OAUTH_CLIENT_ID` …), and on a local install Google also through the linked account; a connector that takes keys (HubSpot, S3) always |
32
- | `start({ space, connector, actions, lang? })` | An OAuth connector: the provider's sign-in page. Only the rights `actions` need are asked for. `lang` (`"en"` or `"de"`) is the language of the page the person comes back to; without it, their browser's |
33
- | `connect({ space, connector, actions, credentials })` | A connector that takes keys: the keys by field key, tried once at the provider, then kept sealed. Keys the provider refuses throw an error with the status `400` and the code `credentials`, whose message says what was wrong. Answers the connection |
34
- | `list(space)`, `get(id)` | What is connected: `{ id, space, connector, label, actions, createdAt }`, the newest first. `label` is the account as the provider names it |
35
- | `call(id, action, input)` | Runs one of the connector's actions with the account. A fresh token is fetched first when the old one runs out |
32
+ | `available(ids)` | Returns the connectors of these ids that a person can connect here now: `{ id, name, auth }`, and for `auth: "api_key"` the `fields` to ask for (`key`, `label`, `placeholder`, `required`, `secret`). An OAuth connector is offered once its client is set up (`GOOGLE_OAUTH_CLIENT_ID` …) or when it registers a client itself. On a local install Google is also offered through the linked engenty account. A connector that takes keys (HubSpot, S3) is always offered |
33
+ | `start({ space, connector, actions, lang? })` | Returns the provider’s sign-in page of an OAuth connector. The provider asks only for the rights that `actions` need. `lang` (`"en"` or `"de"`) is the language of the page the person comes back to; without it, the page follows their browser |
34
+ | `connect({ space, connector, actions, credentials })` | Connects a connector that takes keys. `credentials` holds the keys by field key. The runtime tries them once at the provider and then keeps them sealed. Keys the provider refuses throw an error with the status `400` and the code `credentials`, whose message says what was wrong. Returns the connection |
35
+ | `list(space)`, `get(id)` | Return what is connected: `{ id, space, connector, label, actions, createdAt }`, the newest first. `label` is the account as the provider names it, often an email address |
36
+ | `call(id, action, input)` | Runs one of the connector’s actions with the account. When the token has run out, the runtime fetches a fresh one first |
36
37
  | `remove(id)` | Forgets the connection and its tokens |
37
38
 
38
39
  ## Signing in
39
40
 
40
- `start` gives an address; open it in a window from the studio half. The provider sends the
41
- person back to the runtime (`/api/connect/callback`, the address a wizard's connections use), the
42
- runtime keeps the account under the plugin and the space, and the window posts a message to the
43
- studio and closes:
41
+ `start` returns an address. Open it in a window from the studio half. The provider sends the
42
+ person back to the runtime (`/api/connect/callback`, the address a wizard’s connections use too).
43
+ The runtime keeps the account under the plugin and the space. The window then posts
44
+ `{ type: "wizards:connected", ok }` to the studio and closes:
44
45
 
45
46
  ```tsx
46
47
  const { url } = await studio.api.post<{ url: string }>(`/connect?space=${space.id}`);
47
48
  window.open(url, "connect", "width=520,height=700");
48
49
 
49
50
  window.addEventListener("message", (event) => {
50
- if (event.data?.type === "wizards:connected") {
51
+ if (event.data?.type === "wizards:connected" && event.data.ok) {
51
52
  refetch();
52
53
  }
53
54
  });
54
55
  ```
55
56
 
56
- - A second sign-in to the same account for the same space replaces the first one's tokens and
57
- actions; it does not add a second connection.
57
+ - A second sign-in to the same account for the same space replaces the first one’s tokens and
58
+ actions. It does not add a second connection.
58
59
  - A local install without a Google client of its own connects Google through the linked
59
- engenty account. Without a linked account `start` throws an error with the status `409` and
60
+ engenty account. Without a linked account, `start` throws an error with the status `409` and
60
61
  the code `account`, whose message says what to do.
61
62
 
62
63
  ## What `call` refuses
63
64
 
64
- - An action the connection was not made for: connect again with that action in `actions`.
65
- - What the provider refuses: its error, with the status and the first words of its answer. A
66
- connection the person removed at the provider answers so on the next call.
65
+ - An action the connection was not made for. Connect again with that action in `actions`.
66
+ - What the provider refuses. `call` throws the provider’s error, with the status and the first
67
+ words of its answer. If the person removed the connection at the provider, the next call
68
+ fails this way.
67
69
 
68
70
  ## Where it is kept
69
71
 
70
- The table `plugin_connection` of the tenant's database, by plugin and space. A plugin sees only
71
- its own connections. Deleting a space deletes them. Unloading or removing the plugin leaves them.
72
+ The connections are kept in the table `plugin_connection` of the tenant’s database, by plugin
73
+ and space. A plugin sees only its own connections. Deleting a space deletes them. Unloading or
74
+ removing the plugin leaves them in place.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Events
3
- description: Do something when a run ends or a space changes — keep who it was, post a message, read a new document.
4
- version: 0.3.2
3
+ description: Do something when a run ends or a space changes – keep who it was, post a message, read a new document.
4
+ version: 0.5.0
5
5
  ---
6
6
 
7
7
  A plugin can listen to runs that reach their end, and to spaces that change.
@@ -35,12 +35,14 @@ server.on("run.done", async ({ run, wizard, values }) => {
35
35
 
36
36
  | Event | A space | Gets |
37
37
  |---|---|---|
38
- | `space.created` | was made, here or by a local install's sync | `{ space: { id } }` |
39
- | `space.updated` | changed its title, about, colours, facts or systems | `{ space: { id } }` |
38
+ | `space.created` | was made here, or arrived from engenty wizards on someone’s computer | `{ space: { id } }` |
39
+ | `space.updated` | changed its name, its brand (Info & brand), its facts or its connected systems, or arrived again from a computer | `{ space: { id } }` |
40
40
  | `space.deleted` | was deleted | `{ space: { id } }` |
41
41
  | `space.file.ready` | has a file that was read: a document is in the index now | `{ space: { id }, file: { id, name, kind, mime } }` |
42
42
  | `space.file.removed` | lost a file | `{ space: { id }, file: { id, name, kind, mime } }` |
43
43
 
44
+ `file.kind` is `"document"`, `"logo"`, `"asset"` or `"pattern"`.
45
+
44
46
  ```ts
45
47
  // A document arrived: read it into the wiki.
46
48
  server.on("space.file.ready", async ({ space, file }) => {
@@ -50,7 +52,7 @@ server.on("space.file.ready", async ({ space, file }) => {
50
52
  });
51
53
  ```
52
54
 
53
- The space events are not waited for: the request that changed the space answers before its
55
+ Nothing waits for the space events: the request that changed the space answers before its
54
56
  listeners are done.
55
57
 
56
58
  ## What a run listener gets
@@ -58,24 +60,24 @@ listeners are done.
58
60
  | | |
59
61
  |---|---|
60
62
  | `run.id`, `run.wizardId` | The run and its wizard |
61
- | `run.mode` | `"live"`: a real run, over the wizard's link or from an AI app. `"test"`: a test run |
63
+ | `run.mode` | `"live"`: a real run, over the wizard’s link or from an AI app. `"test"`: a test run |
62
64
  | `run.status` | `"done"`, `"failed"` or `"cancelled"` |
63
65
  | `wizard` | `{ id, title, projectId }` |
64
66
  | `values` | What the person answered, by field id |
65
67
 
66
- `values` holds answers as the wizard asked for them. Which fields exist depends on the wizard: a
67
- listener that wants an e-mail address looks for a field with the id it expects and does nothing
68
- when it is missing. Check the type of every value you use.
68
+ `values` holds the answers as the wizard asked for them. Which fields exist depends on the
69
+ wizard. A listener that wants an email address looks for a field with the id it expects and does
70
+ nothing when it is missing. Check the type of every value you use.
69
71
 
70
72
  ## Rules a listener runs under
71
73
 
72
- - **Inside the run's tenant.** `server.getTenantDb()` is that tenant's database.
73
- - **After the run ended.** A listener cannot change the run or its result.
74
- - **It cannot fail the run.** A listener that throws is logged with the plugin's id.
75
- - **It can be told twice.** A finished run that is redone and ends again fires the event again.
76
- Write listeners so that a second call does no harm: update a row instead of adding one, or
77
- remember the run's id.
78
- - **Nobody waits for it.** Give outside calls a time limit:
74
+ - **It runs inside the run’s tenant.** `server.getTenantDb()` is that tenant’s database.
75
+ - **It runs after the run ended.** A listener cannot change the run or its result.
76
+ - **It cannot fail the run.** A listener that throws is logged with the plugin’s id.
77
+ - **It can be called twice.** A finished run that is redone and ends again fires the event
78
+ again. Write listeners so that a second call does no harm: update a row instead of adding one,
79
+ or remember the run’s id.
80
+ - **Nothing waits for it.** Give outside calls a time limit:
79
81
 
80
82
  ```ts
81
83
  await fetch(url, { method: "POST", body, signal: AbortSignal.timeout(10_000) });
@@ -84,4 +86,4 @@ when it is missing. Check the type of every value you use.
84
86
  ## Test runs
85
87
 
86
88
  Test runs fire the same events with `run.mode === "test"`. A plugin that keeps data about real
87
- people, or tells someone outside, leaves them out, as the example above does.
89
+ people, or tells someone outside, leaves test runs out, as the example above does.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Examples
3
3
  description: Two plugins in the repository to read, run and copy.
4
- version: 0.3.2
4
+ version: 0.5.0
5
5
  ---
6
6
 
7
7
  The repository has two example plugins. Load them from a checkout with one line in `.env.local`:
@@ -13,7 +13,7 @@ PLUGINS_DIR=examples/plugins
13
13
  ## notify: one file
14
14
 
15
15
  [examples/plugins/notify.ts](https://github.com/engenty/wizards/blob/main/examples/plugins/notify.ts)
16
- posts a line to an address whenever a real run of a wizard reached its end.
16
+ posts a line to an address whenever a real run of a wizard reaches its end.
17
17
 
18
18
  ```ts
19
19
  import type { WizardsPluginFactory } from "@engenty-wizards/plugin-sdk";
@@ -42,8 +42,8 @@ export default plugin;
42
42
 
43
43
  | It shows | |
44
44
  |---|---|
45
- | A plugin of one file | Its id is the file's name |
46
- | A setting | `NOTIFY_URL` in the install's `.env`, read at load time |
45
+ | A plugin of one file | Its id is the file’s name |
46
+ | A setting | `NOTIFY_URL` in the install’s `.env`, read at load time |
47
47
  | A listener | Test runs left out, a time limit on the call |
48
48
 
49
49
  ## run-log: both halves
@@ -58,8 +58,8 @@ keeps a line for every run that ended and shows them in the studio.
58
58
  | `migrations/0002_space.sql` | A column added later: the space of each line |
59
59
  | `src/schema.ts` | The same table for Drizzle |
60
60
  | `src/plugin.ts` | A listener on the three run events (`run.done`, `run.failed`, `run.cancelled`), two routes (one for admins only, one that filters by space) and a tool, `run-log.recent` |
61
- | `ui/messages.ts` | Words in German and English |
62
- | `ui/plugin.tsx` | A section of the space page with the space's last runs, under Results, a page with the whole log, and a section of the settings that empties the log |
61
+ | `ui/messages.ts` | Its texts in English and German |
62
+ | `ui/plugin.tsx` | A section of the space page under Results with the space’s last runs, a page with the whole log, and a settings section that empties the log |
63
63
  | `package.json` | A workspace package whose `build` script builds the studio half |
64
64
 
65
65
  Build its studio half once, or on every save:
@@ -75,11 +75,12 @@ node scripts/build-plugin.mjs examples/plugins/run-log --watch
75
75
  Then, in the studio:
76
76
 
77
77
  1. Test a wizard to its end.
78
- 2. The house icon in the app bar opens the space's page; under Results, "Runs" stands below the
79
- results: the last five runs of the space's wizards. Its last line opens the page with the
80
- whole log.
81
- 3. Settings → Runs shows how many lines are kept and deletes them.
82
- 4. An AI step can list the tool "Run log" and tell how the last runs ended.
78
+ 2. Open the space’s Results: choose “Results” under Space in the sidebar, or open the space’s
79
+ page with the house icon in the app bar and go to Results. “Runs” stands below the results
80
+ and shows the last five runs of the space’s wizards. Its last line, “All … runs”, opens the
81
+ page with the whole log.
82
+ 3. Settings → Runs shows how many lines are kept, and “Delete all” deletes them.
83
+ 4. An AI step can list the tool “Run log” and tell how the last runs ended.
83
84
 
84
85
  ## The plugin of these pages
85
86
 
@@ -97,4 +98,4 @@ The `contacts` plugin these pages build up, piece by piece:
97
98
 
98
99
  [apps/runtime/test/plugins.test.ts](https://github.com/engenty/wizards/blob/main/apps/runtime/test/plugins.test.ts)
99
100
  writes small plugins into a folder and exercises them: finding, loading, a plugin that fails,
100
- routes, tables per tenant, tools in a run, events, reloading.
101
+ routes, tables per tenant, tools in a run, events and reloading.
@@ -1,31 +1,34 @@
1
1
  ---
2
2
  title: Plugins
3
3
  description: What a plugin is, what its two halves can add, and what it may touch.
4
- version: 0.3.2
4
+ version: 0.5.0
5
5
  ---
6
6
 
7
- A plugin adds to a runtime without changing its code. The runtime finds plugins at start, loads
8
- them from their files and loads one again when its files change.
7
+ A plugin adds to a runtime without changing its code. The runtime finds plugins when it starts,
8
+ loads them from their files and loads a plugin again when its files change.
9
9
 
10
10
  ## What a plugin can add
11
11
 
12
12
  | It adds | Where it shows | Page |
13
13
  |---|---|---|
14
- | A tool for AI steps | In a step's tool list, in the assistant's and the MCP authoring guide | [Tools](./tools.md) |
15
- | A runner: a door a wizard runs through, with the run API that drives runs from it | In the share dialog's channels, at `/w/<token>/<runner>`, on the wizard's first page | [Runners](./runners.md) |
16
- | A block and tools for every AI step of a space | In the steps' instructions | [The space](./space.md) |
17
- | Pages, tables and files of a space's Knowledge, with Kategorien | In Knowledge, and in what `project_search` finds | [The space](./space.md#knowledge-a-plugin-writes) |
18
- | Texts in a space's search index | In what `project_search` finds | [The space](./space.md#the-search-index) |
19
- | Tools of the studio's assistant, and their cards | In the assistant's chat, on every page | [The space](./space.md#tools-of-the-space-assistant) |
20
- | Routes | Below `/api/studio/plugins/<id>`, for programs with a key below `/api/v1/plugins/<id>`; public ones below `/api/public/plugins/<id>` | [Routes](./routes.md) |
21
- | Tables | In every tenant's database | [Tables](./tables.md) |
14
+ | A tool for AI steps | In a step’s tool list, in the assistant’s and the MCP authoring guide | [Tools](./tools.md) |
15
+ | A runner: a door a wizard runs through, with the run API that drives runs from it | In the share dialog’s channels, at `/w/<token>/<runner>`, on the wizard’s first page | [Runners](./runners.md) |
16
+ | A runner’s settings and setup in the share dialog | In the share dialog, behind its gear and behind “Set up” in the runner’s row | [Runners](./runners.md#the-runners-part-of-the-share-dialog) |
17
+ | A block and tools for every AI step of a space | In the steps’ instructions | [The space](./space.md) |
18
+ | Pages, tables and files of a space’s Knowledge, with their categories | In Knowledge, and in what `project_search` finds | [The space](./space.md#knowledge-a-plugin-writes) |
19
+ | Texts in a space’s search index | In what `project_search` finds | [The space](./space.md#the-search-index) |
20
+ | Tools of the studio’s assistant, and their cards | In the assistant’s chat, on every page. For now the assistant is off unless it is switched on | [The space](./space.md#tools-of-the-space-assistant) |
21
+ | Routes | Below `/api/studio/plugins/<id>`, for programs with a key below `/api/v1/plugins/<id>`; public ones below `/api/public/plugins/<id>`, one for every tenant below `/api/public/plugins/<id>/shared` | [Routes](./routes.md) |
22
+ | Tables | In every tenant’s database | [Tables](./tables.md) |
22
23
  | A listener on runs that end and spaces that change | Nowhere: it works in the background | [Events](./events.md) |
23
24
  | A job, again and again | Nowhere: it works in the background | [The server half](./server.md#jobs) |
24
- | An account of a space (a calendar, a mailbox), signed in through a built-in connector | Where the plugin's own pages offer it | [Accounts](./connections.md) |
25
+ | The team’s own number for texts and calls, on engenty.ai | Where the plugin’s runner and pages use it | [The server half](./server.md#numbers-of-the-manage-app) |
26
+ | An account of a space (a calendar, a mailbox), signed in through a built-in connector | Where the plugin’s own pages offer it | [Accounts](./connections.md) |
25
27
  | A wizard as a template | First among the templates of a new wizard, and in the MCP `list_starters` | [Starters](./starters.md) |
26
28
  | A page of the studio | Behind an icon in the app bar, or at its address | [The studio half](./studio.md) |
27
- | A section of the settings | In the settings' list | [The studio half](./studio.md) |
28
- | A section of the space page | In one of its parts, below the part's own sections | [The studio half](./studio.md#the-space) |
29
+ | A section of the settings | In the settings’ list | [The studio half](./studio.md) |
30
+ | A section of the space page | In one of its parts, below the part’s own sections | [The studio half](./studio.md#the-space) |
31
+ | A part of the space page | In the space’s menu, beside Info & brand, Knowledge, Data and Results | [The studio half](./studio.md#a-part-of-the-plugins-own) |
29
32
 
30
33
  ## Two halves
31
34
 
@@ -35,9 +38,9 @@ them from their files and loads one again when its files change.
35
38
  | Runs in | The runtime | The studio, after sign-in |
36
39
  | Loaded | As TypeScript, no build | As the built script |
37
40
  | Types | `@engenty-wizards/plugin-sdk` | `@engenty-wizards/plugin-sdk/studio` |
38
- | Adds | Tools, runners, routes, tables, listeners, jobs, starters, accounts, Knowledge, the space's block, index and assistant tools | Pages, icons in the app bar, sections of the settings and of the space page, a runner's part of the share dialog, cards in the assistant's chat |
41
+ | Adds | Tools, runners, routes, tables, listeners, jobs, starters, accounts, Knowledge, the space’s block, index and assistant tools | Pages, icons in the app bar, sections of the settings and of the space page, parts of the space page, a runner’s settings and setup in the share dialog, cards in the assistant’s chat |
39
42
 
40
- A plugin has one half or both. The studio half talks to the server half over the plugin's own
43
+ A plugin has one half or both. The studio half talks to the server half over the plugin’s own
41
44
  routes.
42
45
 
43
46
  ```mermaid
@@ -53,21 +56,23 @@ flowchart LR
53
56
 
54
57
  ## What a plugin may touch
55
58
 
56
- A plugin runs inside the runtime's process with all of its rights. It reads every tenant's data,
57
- the install's settings and the files of the machine. There is no sandbox and no permission list.
59
+ A plugin runs inside the runtime’s process with all of its rights. It can read every tenant’s
60
+ data, the install’s settings and the files of the computer it runs on. There is no sandbox and
61
+ no permission list.
58
62
 
59
63
  - Install only code you know.
60
64
  - A plugin for others says in its own description what it reads and where it sends it.
61
65
 
62
66
  ## Not the Claude Code plugin
63
67
 
64
- The "Claude Code plugin" of engenty wizards is something else: what a runtime hands to Claude
65
- Code (`plugin/` in the repository). These pages are about plugins of the runtime.
68
+ The “Claude Code plugin” of engenty wizards is something else: it is what a runtime hands to
69
+ Claude Code (`plugin/` in the repository). These pages are about plugins of the runtime.
66
70
 
67
71
  ## Not there yet
68
72
 
69
- - Connectors of its own, tools for MCP clients and AI clients from a plugin. A plugin connects
73
+ - A plugin can’t bring connectors of its own, or tools for MCP clients and AI apps. It connects
70
74
  accounts through the built-in connectors: [Accounts](./connections.md).
71
- - New kinds of steps or fields: the public pages of a wizard load no plugin. A plugin's runner
72
- is served whole at its own sub-path; nothing is loaded into the page or the chat.
73
- - Building a studio half without a checkout of the repository.
75
+ - A plugin can’t add new kinds of steps or fields: the public pages of a wizard load no plugin.
76
+ A plugin’s runner is served whole at its own sub-path; nothing is loaded into the page or the
77
+ chat.
78
+ - You can’t build a studio half without a checkout of the repository.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Files and manifest
3
3
  description: Where the runtime looks for plugins, what counts as one, and what engenty.plugin.json says.
4
- version: 0.3.2
4
+ version: 0.5.0
5
5
  ---
6
6
 
7
7
  ## Where the runtime looks
@@ -12,9 +12,9 @@ version: 0.3.2
12
12
  | Each folder of `PLUGINS_DIR` (comma-separated) | Plugins of this install |
13
13
 
14
14
  - An installed app looks in `~/.engenty/wizards/plugins` unless its `.env` names another folder.
15
- - From a checkout `PLUGINS_DIR` is empty. `PLUGINS_DIR=examples/plugins` in `.env.local` loads
15
+ - In a checkout `PLUGINS_DIR` is empty. `PLUGINS_DIR=examples/plugins` in `.env.local` loads
16
16
  the examples.
17
- - A runtime that watches its plugins makes a folder of `PLUGINS_DIR` that is missing.
17
+ - A runtime that watches its plugins creates a folder of `PLUGINS_DIR` that is missing.
18
18
 
19
19
  ## What counts as a plugin
20
20
 
@@ -22,17 +22,18 @@ In such a folder:
22
22
 
23
23
  | Entry | Is |
24
24
  |---|---|
25
- | `notify.ts`, `notify.js` | A plugin of one file. Its id is the file's name |
25
+ | `notify.ts`, `notify.js` | A plugin of one file. Its id is the file’s name |
26
26
  | `contacts/engenty.plugin.json` | A plugin with a manifest |
27
- | `hello/index.ts`, `hello/index.js` | A plugin without a manifest. Its id is the folder's name |
27
+ | `hello/index.ts`, `hello/index.js` | A plugin without a manifest. Its id is the folder’s name |
28
28
  | `node_modules/<package>`, `node_modules/@scope/<package>` | Installed packages that carry a manifest |
29
29
 
30
- - Names that begin with `.` or `_` are skipped.
31
- - `.mjs` files are not read: Node keeps such a file once imported, so it could not load again.
32
- - Of two plugins with one id the first found stays. The other shows under "Not a plugin" in
33
- Settings → Plugins, as does a manifest that cannot be read.
30
+ - The runtime skips names that begin with `.` or `_`.
31
+ - It doesn’t read `.mjs` files: Node keeps such a file once it is imported, so it could not load
32
+ again.
33
+ - Of two plugins with the same id, the first one found stays. The other shows under “Not a
34
+ plugin” in Settings → Plugins, as does a manifest that cannot be read.
34
35
 
35
- ## A plugin's folder
36
+ ## A plugin’s folder
36
37
 
37
38
  ```
38
39
  contacts/
@@ -50,39 +51,39 @@ contacts/
50
51
  package.json only if it has dependencies of its own
51
52
  ```
52
53
 
53
- Only the manifest is required. A plugin with a studio half is a folder with a manifest.
54
+ Only the manifest is required. A plugin with a studio half must be a folder with a manifest.
54
55
 
55
56
  ## The manifest
56
57
 
57
- `engenty.plugin.json` is the file an engenty module has. Fields this runtime does not know are
58
- kept as they are.
58
+ `engenty.plugin.json` is the same file an engenty module has. The runtime keeps fields it
59
+ doesn’t know as they are.
59
60
 
60
61
  ```json
61
62
  {
62
63
  "id": "contacts",
63
64
  "name": "Contacts",
64
65
  "version": "0.1.0",
65
- "description": "Keeps the e-mail address of everyone who ran a wizard to its end."
66
+ "description": "Keeps the email address of everyone who ran a wizard to its end."
66
67
  }
67
68
  ```
68
69
 
69
70
  | Field | | Default |
70
71
  |---|---|---|
71
- | `id` | Lower case, digits and `-`, starting with a letter, at most 40 characters. Part of the plugin's addresses and of its tools' ids | required |
72
+ | `id` | Lower case, digits and `-`, starting with a letter, at most 40 characters. Part of the plugin’s addresses and of its tools’ ids | required |
72
73
  | `name` | Shown in the settings | required |
73
74
  | `version` | Shown in the settings | `0.0.0` |
74
75
  | `description` | Shown in the settings | |
75
- | `server` | The server half, from the plugin's folder | `src/plugin.ts`, then `src/plugin.js`, then `dist/plugin.js` |
76
+ | `server` | The server half, from the plugin’s folder | `src/plugin.ts`, then `src/plugin.js`, then `dist/plugin.js` |
76
77
  | `studio` | The built studio half | `dist/client.js` |
77
- | `styles` | The built studio half's styles | `dist/client.css` |
78
+ | `styles` | The built studio half’s styles | `dist/client.css` |
78
79
 
79
- A path in the manifest must stay inside the plugin's folder.
80
+ A path in the manifest must stay inside the plugin’s folder.
80
81
 
81
82
  ## Dependencies
82
83
 
83
84
  | The plugin imports | It comes from |
84
85
  |---|---|
85
- | `@engenty-wizards/plugin-sdk`, `@engenty-wizards/plugin-sdk/thread`, `zod`, `drizzle-orm`, `drizzle-orm/sqlite-core` | The runtime's own copies, wherever the plugin's file is |
86
+ | `@engenty-wizards/plugin-sdk`, `@engenty-wizards/plugin-sdk/thread`, `zod`, `drizzle-orm`, `drizzle-orm/sqlite-core` | The runtime’s own copies, wherever the plugin’s file is |
86
87
  | Its own files | Beside it, as TypeScript |
87
88
  | Anything else | A `node_modules` the plugin brings beside it |
88
89
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Quick start
3
3
  description: A tool for AI steps in one file. No build, no restart.
4
- version: 0.3.2
4
+ version: 0.5.0
5
5
  ---
6
6
 
7
7
  You write one file. The running app finds it, and every AI step can use the tool in it.
@@ -10,10 +10,10 @@ You write one file. The running app finds it, and every AI step can use the tool
10
10
 
11
11
  | You run | The folder |
12
12
  |---|---|
13
- | The installed app (`wizards`) | `~/.engenty/wizards/plugins` |
14
- | A checkout (`pnpm dev`) | The folders `PLUGINS_DIR` names in `.env.local`, for example `PLUGINS_DIR=../my-plugins`. A relative path starts at the checkout's root |
13
+ | engenty wizards on your computer (`wizards`) | `~/.engenty/wizards/plugins` |
14
+ | A checkout (`pnpm dev`) | The folders that `PLUGINS_DIR` names in `.env.local`, for example `PLUGINS_DIR=../my-plugins`. A relative path starts at the checkout’s root |
15
15
 
16
- Start the app. It makes the folder if it is missing and watches it while it runs.
16
+ Start the app. It creates the folder if it is missing and watches it while it runs.
17
17
 
18
18
  ## 2. Write the plugin
19
19
 
@@ -48,21 +48,22 @@ export default definePlugin((wizards) => {
48
48
  });
49
49
  ```
50
50
 
51
- - The file's name is the plugin's id: `workdays`.
52
- - The tool's full id is `workdays.count`.
53
- - `@engenty-wizards/plugin-sdk` and `zod` come from the app. Nothing to install.
51
+ - The file’s name is the plugin’s id: `workdays`.
52
+ - The tool’s full id is `workdays.count`.
53
+ - `@engenty-wizards/plugin-sdk` and `zod` come from the app, so you don’t install anything.
54
54
 
55
55
  ## 3. See it
56
56
 
57
57
  The app loaded the file the moment you saved it.
58
58
 
59
- - **Settings → Plugins** lists `workdays`, with `workdays.count` under "Tools for steps".
59
+ - **Settings → Plugins** lists `workdays`, with `workdays.count` under “Tools for steps”.
60
60
  - **In the editor**, open an AI step: `workdays.count` is in its list of tools, beside
61
- `web_search` and the other built-in ones; the line below the list names it "Working days".
62
- - **In the conversation**, ask for it: "Add a step that counts the working days between the two
63
- dates." The assistant knows the tool from its description.
61
+ `web_search` and the other built-in ones. The line below the list says “workdays.count =
62
+ Working days”.
63
+ - **In the editor’s chat**, ask for it: “Add a step that counts the working days between the
64
+ two dates.” The assistant knows the tool from its description.
64
65
 
65
- In a wizard's definition the step lists the tool by its full id:
66
+ In a wizard’s definition the step lists the tool by its full id:
66
67
 
67
68
  ```json
68
69
  {
@@ -78,10 +79,10 @@ In a wizard's definition the step lists the tool by its full id:
78
79
 
79
80
  ## 4. Change it
80
81
 
81
- Edit the file and save. The plugin loads again; the next step that runs uses the new code.
82
+ Edit the file and save. The plugin loads again, and the next step that runs uses the new code.
82
83
 
83
- If the file has an error, Settings → Plugins says "The server half did not load" with the
84
- reason. Mend the file and save again.
84
+ If the file has an error, Settings → Plugins says “The server part didn’t load. Check the plugin
85
+ and reload” with the reason. Fix the file and save it again.
85
86
 
86
87
  ## Next
87
88