@engenty/wizards-runtime 0.7.5 → 0.7.7
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/apps/runtime/dist/authoring/guide.js +5 -1
- package/apps/runtime/dist/cli/environment.js +2 -0
- package/apps/runtime/dist/cli/main.js +10 -1
- package/apps/runtime/dist/cli/sandbox.js +77 -0
- package/apps/runtime/dist/cli/status.js +9 -0
- package/apps/runtime/dist/debug.js +2 -1
- package/apps/runtime/dist/docs/dev/index.md +6 -1
- package/apps/runtime/dist/docs/dev/integration/channels.md +11 -0
- package/apps/runtime/dist/docs/dev/integration/claude-code-plugin.md +10 -0
- package/apps/runtime/dist/docs/dev/integration/embed.md +10 -0
- package/apps/runtime/dist/docs/dev/integration/index.md +36 -0
- package/apps/runtime/dist/docs/dev/integration/link-and-share.md +10 -0
- package/apps/runtime/dist/docs/dev/integration/mcp-apps.md +10 -0
- package/apps/runtime/dist/docs/dev/integration/mcp.md +10 -0
- package/apps/runtime/dist/docs/dev/integration/meta.json +20 -0
- package/apps/runtime/dist/docs/dev/integration/openui.md +181 -0
- package/apps/runtime/dist/docs/dev/integration/own-ui.md +10 -0
- package/apps/runtime/dist/docs/dev/integration/results.md +11 -0
- package/apps/runtime/dist/docs/dev/integration/wordpress.md +10 -0
- package/apps/runtime/dist/docs/dev/meta.json +1 -1
- package/apps/runtime/dist/docs/user/command-line.md +3 -0
- package/apps/runtime/dist/docs/user/server.md +1 -1
- package/apps/runtime/dist/engine/steps.js +2 -1
- package/apps/runtime/dist/env.js +10 -26
- package/apps/runtime/dist/routes/runs.js +14 -1
- package/apps/runtime/dist/sandbox/agentos-package.js +73 -0
- package/apps/runtime/dist/sandbox/agentos.js +162 -0
- package/apps/runtime/dist/sandbox/docker.js +32 -62
- package/apps/runtime/dist/sandbox/index.js +37 -8
- package/apps/runtime/dist/sandbox/install.js +122 -0
- package/apps/runtime/dist/sandbox/mastra.js +71 -0
- package/apps/runtime/dist/services/spaces.js +2 -1
- package/apps/runtime/dist/tools/code.js +133 -0
- package/apps/runtime/dist/tools/connector.js +6 -0
- package/apps/runtime/dist/tools/index.js +14 -3
- package/apps/web/dist/assets/{AboutDialog-D4mvc-zu.js → AboutDialog-BP8-Ugxf.js} +1 -1
- package/apps/web/dist/assets/{ChangelogDialog-DLqpJsF6.js → ChangelogDialog-CD6CQNW9.js} +1 -1
- package/apps/web/dist/assets/{ChatView-3laypRcE.js → ChatView-4T0QarEr.js} +1 -1
- package/apps/web/dist/assets/{EditorPage-BalA5U2Y.js → EditorPage-CWdV7Xdn.js} +3 -3
- package/apps/web/dist/assets/{FlowPreview-CusP7ci9.js → FlowPreview-Dj2gAfuf.js} +1 -1
- package/apps/web/dist/assets/{Harness-iYLtOLaK.js → Harness-SLbsntQF.js} +1 -1
- package/apps/web/dist/assets/{NewWizardChannels-CbwJ9A56.js → NewWizardChannels-CsDMlji7.js} +1 -1
- package/apps/web/dist/assets/{NewWizardPage-BOBYiB9i.js → NewWizardPage-_bFYjlgh.js} +1 -1
- package/apps/web/dist/assets/{OnboardingPage-CUwCiVIr.js → OnboardingPage-DObQeCDg.js} +1 -1
- package/apps/web/dist/assets/{ProjectPage-Bb16MdYG.js → ProjectPage-DX-oNLWy.js} +1 -1
- package/apps/web/dist/assets/{PublicRunner-BCt7Q6C-.js → PublicRunner-Bn9rVNEb.js} +1 -1
- package/apps/web/dist/assets/{ReadOnly-kIHX2TEy.js → ReadOnly-CK0piLUV.js} +1 -1
- package/apps/web/dist/assets/{RunDrawer-hZ9oeSXu.js → RunDrawer-CVMTLse_.js} +1 -1
- package/apps/web/dist/assets/{RunnerView-DUS9fPmx.js → RunnerView-Cjhuu9ua.js} +1 -1
- package/apps/web/dist/assets/{SettingsPage-BzwR50fi.js → SettingsPage-DTzuiSAj.js} +1 -1
- package/apps/web/dist/assets/{SetupPage-gAp7rPxp.js → SetupPage-D9jlhgiP.js} +1 -1
- package/apps/web/dist/assets/{SharePage-DqZWHva_.js → SharePage-Cc3Opj2F.js} +1 -1
- package/apps/web/dist/assets/changelog-CJNkd1_L.js +1 -0
- package/apps/web/dist/assets/{esm-DXeMu8Lb.js → esm-CfnFE_jE.js} +1 -1
- package/apps/web/dist/assets/{index-C5Sm7tTR.js → index-B5F1_qA_.js} +4 -4
- package/apps/web/dist/assets/{lock-R_CfU0Xo.js → lock-DAvRJY4B.js} +1 -1
- package/apps/web/dist/assets/oss-credits-X2JPiMOR.js +1 -0
- package/apps/web/dist/assets/{phone-CgrIS4_-.js → phone-BWOB67tX.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-2IMOOlLl.js → settings-menu-CEQlVs1O.js} +1 -1
- package/apps/web/dist/assets/{ui-dzGvc3xk.js → ui-BmR_4eL2.js} +1 -1
- package/apps/web/dist/assets/{upload-BSuTilFF.js → upload-pBKn2EFp.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/apps/web/dist/mcp/flow.html +2 -2
- package/node_modules/@engenty/wizards/dist/openui/Wizard.d.ts +20 -0
- package/node_modules/@engenty/wizards/dist/openui/Wizard.js +62 -0
- package/node_modules/@engenty/wizards/dist/openui/index.d.ts +9 -0
- package/node_modules/@engenty/wizards/dist/openui/index.js +9 -0
- package/node_modules/@engenty/wizards/dist/openui/message.d.ts +11 -0
- package/node_modules/@engenty/wizards/dist/openui/message.js +69 -0
- package/node_modules/@engenty/wizards/dist/openui/run.d.ts +8 -0
- package/node_modules/@engenty/wizards/dist/openui/run.js +137 -0
- package/node_modules/@engenty/wizards/dist/openui/server.d.ts +37 -0
- package/node_modules/@engenty/wizards/dist/openui/server.js +77 -0
- package/node_modules/@engenty/wizards/package.json +4 -1
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +4 -1
- package/node_modules/@engenty-wizards/shared/dist/definition.js +1 -0
- package/node_modules/@engenty-wizards/shared/dist/fit.js +7 -2
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +14 -0
- package/node_modules/@engenty-wizards/shared/dist/run.js +2 -0
- package/package.json +4 -3
- package/apps/web/dist/assets/changelog-DugmCNSf.js +0 -1
- package/apps/web/dist/assets/oss-credits-cZ9NUaLZ.js +0 -1
|
@@ -133,7 +133,7 @@ type AgentStep = {
|
|
|
133
133
|
// (fields name the keys later steps read). Use it where a model would only fetch and copy
|
|
134
134
|
// data (free appointment times) — it answers in a second instead of half a minute.
|
|
135
135
|
// String inputs are templates; a filled-in whole number or true/false is passed as one.
|
|
136
|
-
tools: ("web_search"|"web_fetch"|"browser"|"sandbox"|"image"|"http"|"pages")[]
|
|
136
|
+
tools: ("web_search"|"web_fetch"|"browser"|"sandbox"|"image"|"http"|"pages"|"code")[]
|
|
137
137
|
mcp?: string[] // ids of the project's MCP servers this step may use
|
|
138
138
|
connections?: string[] // ids of wizard connections this step may read (mail → mail_search, mail_read, mail_save)
|
|
139
139
|
output: { format: "text"|"markdown"|"json", fields?: { id, kind: "text"|"number"|"list"|"table"|"yesno"|"choice"|"score", description, columns?: string[], options?: string[] }[], schema?: Schema, surface?: SurfaceComponent[] | true }
|
|
@@ -156,6 +156,10 @@ type AgentStep = {
|
|
|
156
156
|
// project_list (by categories), page_read / table_read / project_document (an item whole, by its path).
|
|
157
157
|
// "pages" brings: page_read / page_write — Markdown pages of the space the wizard keeps for every run (notes, a log
|
|
158
158
|
// that grows with append), shown to the admin under Space → Data; page_read also reads Knowledge by path.
|
|
159
|
+
// "code" brings: execute_typescript — the model writes one program that calls the step's other tools (not the browser) as
|
|
160
|
+
// functions: loops, Promise.all, filtering, sums; only its answer reaches the model. For many calls of one kind (fetch 30
|
|
161
|
+
// pages, read every row of a list, search a mailbox month by month). It needs other tools to call; a change the person
|
|
162
|
+
// must allow first is never made from a program.
|
|
159
163
|
// "browser" brings: browser_open/read/click/type/select/scroll/press/back/wait, browser_screenshot (the model looks at the page),
|
|
160
164
|
// browser_run_fast (a decision model clicks through a page's mechanical part, where one is reached),
|
|
161
165
|
// browser_request_credentials (the PERSON types a login into the page — the model never sees it; sign-ins can be remembered),
|
|
@@ -8,6 +8,7 @@ import { CLIENTS, nodeIsCurrent } from "./machine.js";
|
|
|
8
8
|
import { mcp } from "./mcp.js";
|
|
9
9
|
import { menu } from "./menu.js";
|
|
10
10
|
import { logsCommand, reportCommand } from "./report.js";
|
|
11
|
+
import { sandboxCommand } from "./sandbox.js";
|
|
11
12
|
import { setup } from "./setup.js";
|
|
12
13
|
import { open, start, studio } from "./start.js";
|
|
13
14
|
import { autostart, restart, status, stop } from "./status.js";
|
|
@@ -40,6 +41,8 @@ ${line(`${command()} restart`, "restart it, e.g. to switch to a newly installed
|
|
|
40
41
|
${line(`${command()} update`, "install the latest version")}
|
|
41
42
|
${line(`${command()} autoupdate`, "updates by themselves: add on or off (WIZARDS_DISABLE_AUTOUPDATE=1 is off too)")}
|
|
42
43
|
${more("(downloaded in the background, used from the next start; never during a run)")}
|
|
44
|
+
${line(`${command()} sandbox`, "the sandbox where AI steps run code, without Docker: add or remove")}
|
|
45
|
+
${more("(agentOS unless you name another engine, about 340 MB; used from the next start)")}
|
|
43
46
|
${line(`${command()} autostart`, "start it when you log in to this computer: add on or off")}
|
|
44
47
|
${more("(macOS: a LaunchAgent; Linux: a systemd user service)")}
|
|
45
48
|
${line(`${command()} connect`, "add your wizards to your AI apps: every app found, or the ones you name:")}
|
|
@@ -70,6 +73,7 @@ function parse(argv) {
|
|
|
70
73
|
const args = {
|
|
71
74
|
command: "",
|
|
72
75
|
value: "",
|
|
76
|
+
engine: "",
|
|
73
77
|
apps: [],
|
|
74
78
|
paths: [],
|
|
75
79
|
json: false,
|
|
@@ -116,10 +120,13 @@ function parse(argv) {
|
|
|
116
120
|
else if (arg.startsWith("-")) {
|
|
117
121
|
return `Unknown option ${arg}.`;
|
|
118
122
|
}
|
|
119
|
-
else if (["autostart", "autoupdate", "logs", "account"].includes(args.command) &&
|
|
123
|
+
else if (["autostart", "autoupdate", "logs", "account", "sandbox"].includes(args.command) &&
|
|
120
124
|
!args.value) {
|
|
121
125
|
args.value = arg;
|
|
122
126
|
}
|
|
127
|
+
else if (args.command === "sandbox" && !args.engine) {
|
|
128
|
+
args.engine = arg;
|
|
129
|
+
}
|
|
123
130
|
else if (["connect", "disconnect", "features"].includes(args.command)) {
|
|
124
131
|
args.apps.push(arg);
|
|
125
132
|
}
|
|
@@ -199,6 +206,8 @@ async function main(argv) {
|
|
|
199
206
|
return autoUpdateCommand(paths, args.value);
|
|
200
207
|
case "account":
|
|
201
208
|
return accountCommand(paths, args.value, { yes: args.yes });
|
|
209
|
+
case "sandbox":
|
|
210
|
+
return sandboxCommand(paths, args.value, args.engine);
|
|
202
211
|
case "connect":
|
|
203
212
|
case "disconnect":
|
|
204
213
|
return connectCommand(paths, args.apps, args.command === "disconnect");
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { delimiter, dirname, join } from "node:path";
|
|
2
|
+
import { ENGINE_PACKAGES, engineList, installEngine, installedVersion, removeEngine, } from "../sandbox/install.js";
|
|
3
|
+
import { runtimePath } from "./environment.js";
|
|
4
|
+
import { runLogged } from "./exec.js";
|
|
5
|
+
import { findOnPath } from "./machine.js";
|
|
6
|
+
import { busy, cmd, no, ok, tilde } from "./ui.js";
|
|
7
|
+
/** What `sandbox add` installs when no engine is named. */
|
|
8
|
+
const DEFAULT_ENGINE = "agentos";
|
|
9
|
+
/** Where an engine goes: `SANDBOX_ENGINES_DIR/<name>`, else `engines/<name>` in the install's folder. */
|
|
10
|
+
export const engineDirOf = (paths, name) => join(process.env.SANDBOX_ENGINES_DIR?.trim() || join(paths.home, "engines"), name);
|
|
11
|
+
/** The engines installed here, with their versions and the versions this release installs. */
|
|
12
|
+
export function installedEngines(paths) {
|
|
13
|
+
return Object.entries(ENGINE_PACKAGES).flatMap(([name, engine]) => {
|
|
14
|
+
const version = installedVersion(engineDirOf(paths, name));
|
|
15
|
+
return version ? [{ name, label: engine.label, version, current: engine.version }] : [];
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* `wizards sandbox [add|remove] [engine]`: the sandbox where AI steps run code, without Docker.
|
|
20
|
+
* The engines are not part of engenty wizards; `add` downloads one beside the install.
|
|
21
|
+
*/
|
|
22
|
+
export async function sandboxCommand(paths, value, engine = "") {
|
|
23
|
+
const name = engine.toLowerCase() || DEFAULT_ENGINE;
|
|
24
|
+
if ((value === "add" || value === "remove") && !ENGINE_PACKAGES[name]) {
|
|
25
|
+
console.error(`${no} There is no engine “${name}”. ${engineList()}`);
|
|
26
|
+
return 2;
|
|
27
|
+
}
|
|
28
|
+
if (value === "add") {
|
|
29
|
+
return add(paths, name);
|
|
30
|
+
}
|
|
31
|
+
if (value === "remove") {
|
|
32
|
+
removeEngine(engineDirOf(paths, name));
|
|
33
|
+
console.log(`${ok} The sandbox ${ENGINE_PACKAGES[name].label} is removed. It goes away with the next ${cmd("restart")}.`);
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
if (value) {
|
|
37
|
+
console.error(`Use ${cmd("sandbox add")} or ${cmd("sandbox remove")}.`);
|
|
38
|
+
return 2;
|
|
39
|
+
}
|
|
40
|
+
const installed = installedEngines(paths);
|
|
41
|
+
if (!installed.length) {
|
|
42
|
+
console.log(`${no} No sandbox is installed. AI steps can’t run code unless Docker has the engenty-sandbox image. To add one: ${cmd("sandbox add")}`);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
for (const { name, label, version } of installed) {
|
|
46
|
+
console.log(`${ok} The sandbox ${label} ${version} is in ${tilde(engineDirOf(paths, name))}.`);
|
|
47
|
+
}
|
|
48
|
+
console.log(`AI steps run code in ${installed.length === 1 ? "it" : "the first one"}, unless Docker has the engenty-sandbox image or SANDBOX names an engine.`);
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
async function add(paths, name) {
|
|
52
|
+
const engine = ENGINE_PACKAGES[name];
|
|
53
|
+
const unsupported = engine.unsupported?.();
|
|
54
|
+
if (unsupported) {
|
|
55
|
+
console.error(`${no} ${unsupported}`);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
const npm = findOnPath("npm", [dirname(process.execPath), process.env.PATH ?? ""].join(delimiter));
|
|
59
|
+
if (!npm) {
|
|
60
|
+
console.error(`${no} npm wasn’t found next to this Node.js.`);
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
const env = { ...process.env, PATH: runtimePath(paths, process.env) };
|
|
64
|
+
const logFile = join(paths.logs, "install.log");
|
|
65
|
+
const dir = engineDirOf(paths, name);
|
|
66
|
+
const spinner = busy(`Installing the sandbox (${engine.label} ${engine.version}, ${engine.size})…`);
|
|
67
|
+
try {
|
|
68
|
+
await installEngine(name, dir, (args) => runLogged(npm, args, { env, logFile }));
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
spinner.fail(`The sandbox couldn’t be installed: ${err.message}`);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
spinner.stop(`${ok} The sandbox is installed in ${tilde(dir)}.`);
|
|
75
|
+
console.log(`AI steps run code in it from the next start: ${cmd("restart")}`);
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
@@ -6,6 +6,7 @@ import { autoUpdatePolicy, updateNotice } from "./autoupdate.js";
|
|
|
6
6
|
import { installedByScript, isCheckout, packageRoot, packageVersion } from "./home.js";
|
|
7
7
|
import { detectClients, findChrome, findFfmpeg, nodeIsCurrent } from "./machine.js";
|
|
8
8
|
import { findWizardsProcesses, stopProcesses } from "./processes.js";
|
|
9
|
+
import { installedEngines } from "./sandbox.js";
|
|
9
10
|
import { entryUrl, runningRuntime, settings, startInBackground } from "./start.js";
|
|
10
11
|
import { bad, badge, cmd, cyan, dim, no, ok, tilde } from "./ui.js";
|
|
11
12
|
/**
|
|
@@ -45,6 +46,14 @@ export async function status(paths, checks) {
|
|
|
45
46
|
}
|
|
46
47
|
row("Browser", chrome ? `${ok} ${dim(tilde(chrome))}` : `${no} not found (needed for PDF and PNG)`);
|
|
47
48
|
row("ffmpeg", ffmpeg.path ? `${ok} ${ffmpeg.version ?? ""}` : `${no} not found (needed for MP4)`);
|
|
49
|
+
const engines = installedEngines(paths);
|
|
50
|
+
row("Sandbox", engines.length
|
|
51
|
+
? engines
|
|
52
|
+
.map(({ label, version, current }) => version === current
|
|
53
|
+
? `${ok} ${label} ${version}`
|
|
54
|
+
: `${no} ${label} ${version} is outdated (${cmd("sandbox add")} installs ${current})`)
|
|
55
|
+
.join(", ")
|
|
56
|
+
: `${no} not installed (${cmd("sandbox add")} lets AI steps run code)`);
|
|
48
57
|
const { updated, pending } = updateNotice(paths, packageVersion());
|
|
49
58
|
if (updated) {
|
|
50
59
|
console.log(`\n ${ok} Updated to ${updated.to}. What changed: ${cyan(updated.notes)}`);
|
|
@@ -8,6 +8,7 @@ import { logState, startedAt, tail } from "./log.js";
|
|
|
8
8
|
import { managed } from "./manage.js";
|
|
9
9
|
import { modelSettings } from "./models.js";
|
|
10
10
|
import { loadedPlugins } from "./plugins/registry.js";
|
|
11
|
+
import { sandboxEngine } from "./sandbox/index.js";
|
|
11
12
|
import { runIndexOf, tenantOfRun } from "./tenants/control.js";
|
|
12
13
|
import { LOCAL_TENANT } from "./tenants/tenant.js";
|
|
13
14
|
/**
|
|
@@ -41,7 +42,7 @@ export async function status() {
|
|
|
41
42
|
appUrl: env.appUrl,
|
|
42
43
|
manageUrl: env.manage.url || null,
|
|
43
44
|
gatewayUrl: (managed ? env.manage.gatewayUrl : env.local.gatewayUrl) || null,
|
|
44
|
-
sandbox:
|
|
45
|
+
sandbox: sandboxEngine()?.name ?? "off",
|
|
45
46
|
browser: env.browserCdpUrl ? "cdp" : "local",
|
|
46
47
|
files: env.s3.bucket ? "s3" : "data folder",
|
|
47
48
|
database: env.databaseUrl ? "libsql" : "file",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Developer
|
|
3
3
|
description: Extend engenty wizards with plugins – tools for AI steps, routes with their own tables, pages in the studio.
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.3
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
You extend engenty wizards with **plugins**. A plugin adds to a runtime without changing its
|
|
@@ -21,6 +21,11 @@ code, and the runtime loads it from its files while it runs.
|
|
|
21
21
|
A wizard is JSON, and it travels as a `.wizard` file. [The wizard format](./wizard-format.md)
|
|
22
22
|
describes the format, the JSON Schema for your editor and `wizards validate`.
|
|
23
23
|
|
|
24
|
+
## Wizards in other systems
|
|
25
|
+
|
|
26
|
+
[Integration](./integration/index.md) shows how a published wizard reaches other systems: people
|
|
27
|
+
over a link, a website or a channel, AI apps over MCP, and your own code.
|
|
28
|
+
|
|
24
29
|
## What you need
|
|
25
30
|
|
|
26
31
|
- engenty wizards on your computer, or a checkout of
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Channels
|
|
3
|
+
description: Run a wizard as a chat, a conversation or a call, and over WhatsApp, SMS or the phone.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [Channels](../../user/test-and-share.md#channels) in the user guide describes how a
|
|
10
|
+
wizard runs as a chat, a conversation or a call, and over WhatsApp, SMS or the phone. A plugin
|
|
11
|
+
adds a channel of its own with a [runner](../plugins/runners.md).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Claude Code plugin
|
|
3
|
+
description: Build and use wizards from Claude Code with the /wizard command and its skills.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [The Claude Code plugin](../../user/ai-apps.md#the-claude-code-plugin) in the user
|
|
10
|
+
guide shows how you install it.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Embed
|
|
3
|
+
description: Put a published wizard on your website with one script tag.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [Embed in a website](../../user/test-and-share.md#embed-in-a-website) in the user
|
|
10
|
+
guide shows the script tag and its options.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Integration
|
|
3
|
+
description: Bring a published wizard into other systems – for people, for AI apps and for your own code.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A published wizard runs wherever a person can reach it. These pages show how to bring it into
|
|
8
|
+
other systems, from a plain link to a chat that starts the wizard by itself.
|
|
9
|
+
|
|
10
|
+
## For people
|
|
11
|
+
|
|
12
|
+
| | |
|
|
13
|
+
|---|---|
|
|
14
|
+
| [Link and QR code](./link-and-share.md) | The wizard’s own page, as a link or a QR code |
|
|
15
|
+
| [Embed](./embed.md) | The wizard on your website, inline, as a button or a chat |
|
|
16
|
+
| [WordPress](./wordpress.md) | The plugin “engenty wizards” places wizards and reads their results |
|
|
17
|
+
| [Channels](./channels.md) | A chat, a conversation or a call, and WhatsApp, SMS or the phone |
|
|
18
|
+
|
|
19
|
+
## For AI apps
|
|
20
|
+
|
|
21
|
+
| | |
|
|
22
|
+
|---|---|
|
|
23
|
+
| [MCP](./mcp.md) | AI apps list, run and build wizards over the Model Context Protocol |
|
|
24
|
+
| [MCP Apps](./mcp-apps.md) | AI apps that support MCP Apps show the wizard itself, page by page |
|
|
25
|
+
| [Claude Code plugin](./claude-code-plugin.md) | The `/wizard` command and the skills to build and use wizards |
|
|
26
|
+
| [OpenUI](./openui.md) | A chat built with OpenUI runs the wizard inside the conversation |
|
|
27
|
+
|
|
28
|
+
## For your code
|
|
29
|
+
|
|
30
|
+
| | |
|
|
31
|
+
|---|---|
|
|
32
|
+
| [Your own UI](./own-ui.md) | Your app draws the run with `@engenty-wizards/runner` |
|
|
33
|
+
| [Results to your systems](./results.md) | What a run produces goes on to your own systems |
|
|
34
|
+
|
|
35
|
+
Each way starts from a published wizard. [Test and share](../../user/test-and-share.md) in the
|
|
36
|
+
user guide explains how you publish one.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Link and QR code
|
|
3
|
+
description: Hand out a published wizard as a link or a QR code.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [Share](../../user/test-and-share.md#share) in the user guide describes the link, the
|
|
10
|
+
QR code and who can open them.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: MCP Apps
|
|
3
|
+
description: AI apps that support MCP Apps show the wizard itself as a widget, page by page.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [What an app can do](../../user/ai-apps.md#what-an-app-can-do) in the user guide lists
|
|
10
|
+
what an app with MCP Apps shows.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: MCP
|
|
3
|
+
description: AI apps list, run and build wizards over the Model Context Protocol.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [AI apps](../../user/ai-apps.md) in the user guide shows how you add engenty wizards
|
|
10
|
+
to Claude Desktop, Cursor, Codex and other AI apps.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Integration",
|
|
3
|
+
"defaultOpen": true,
|
|
4
|
+
"pages": [
|
|
5
|
+
"index",
|
|
6
|
+
"---For people---",
|
|
7
|
+
"link-and-share",
|
|
8
|
+
"embed",
|
|
9
|
+
"wordpress",
|
|
10
|
+
"channels",
|
|
11
|
+
"---For AI apps---",
|
|
12
|
+
"mcp",
|
|
13
|
+
"mcp-apps",
|
|
14
|
+
"claude-code-plugin",
|
|
15
|
+
"openui",
|
|
16
|
+
"---For your code---",
|
|
17
|
+
"own-ui",
|
|
18
|
+
"results"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Wizards in OpenUI chats
|
|
3
|
+
description: A Wizard component for OpenUI’s React renderer. The chat’s model decides that a wizard runs, and the wizard runs its own pages inside the conversation.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A chat built with [OpenUI](https://github.com/thesysdev/openui) composes its answers as it
|
|
8
|
+
goes: cards, charts, forms and buttons, whatever the model finds fitting. A wizard is the one
|
|
9
|
+
thing in such a chat that runs the same way every time, with the pages, steps and result its
|
|
10
|
+
author defined. `@engenty/wizards/openui` puts the two together: the chat decides that a wizard
|
|
11
|
+
fits and what it already knows, the wizard then runs inside the conversation, and the chat
|
|
12
|
+
hears the result.
|
|
13
|
+
|
|
14
|
+
It is part of `@engenty/wizards`, the package for code outside engenty wizards
|
|
15
|
+
([`packages/wizards/src/openui`](https://github.com/engenty/wizards/tree/main/packages/wizards/src/openui)
|
|
16
|
+
in the repository, under the MIT licence). A whole chat to try it with is `examples/openui-chat`.
|
|
17
|
+
|
|
18
|
+
## What OpenUI is
|
|
19
|
+
|
|
20
|
+
OpenUI (Thesys, MIT) is a way to let a model draw. Three parts matter here:
|
|
21
|
+
|
|
22
|
+
- **A language the model writes.** An answer is a short program: `root = Card([…])` with
|
|
23
|
+
components as calls, such as `TextContent("…")` or `Form(…)`. The model streams it like text.
|
|
24
|
+
- **A React renderer** (`@openuidev/react-lang`) that parses the program as it streams and draws
|
|
25
|
+
it with a **component library**: React components with a name, a description and typed props.
|
|
26
|
+
- **A chat kit** (`@openuidev/react-ui`): the library of chat components, the thread, the
|
|
27
|
+
composer and an `AgentInterface` that puts them together.
|
|
28
|
+
|
|
29
|
+
The model learns the language from the system prompt the library makes. The chat library’s
|
|
30
|
+
prompt is about 14,000 tokens: every component with its props and description, the rules, and
|
|
31
|
+
5 worked examples of whole answers. The model imitates the examples. Nothing in that prompt is
|
|
32
|
+
a fixed flow: every answer, and every form in it, is composed anew.
|
|
33
|
+
|
|
34
|
+
A wizard is the only fixed definition in such a chat. The model writes one line, and from then
|
|
35
|
+
on the wizard’s pages, AI steps, review and result run as its author defined them.
|
|
36
|
+
|
|
37
|
+
## How the Wizard component works
|
|
38
|
+
|
|
39
|
+
```mermaid
|
|
40
|
+
sequenceDiagram
|
|
41
|
+
participant S as Chat server
|
|
42
|
+
participant M as Model
|
|
43
|
+
participant B as Browser (OpenUI renderer)
|
|
44
|
+
participant R as Runtime
|
|
45
|
+
S->>R: GET /api/public/wizards/:token
|
|
46
|
+
R-->>S: title, description, fields
|
|
47
|
+
S->>M: system prompt + wizard rules
|
|
48
|
+
M-->>B: root = Card([TextContent("…"), Wizard("<token>", "<note>", {plate: "W-12345"})])
|
|
49
|
+
B->>R: POST /api/public/wizards/:token/runs
|
|
50
|
+
R-->>B: run id
|
|
51
|
+
loop every step
|
|
52
|
+
R-->>B: the run’s view (stream)
|
|
53
|
+
B->>R: a page’s answers, a review, back
|
|
54
|
+
end
|
|
55
|
+
B->>S: continue_conversation: “The wizard finished.” + result
|
|
56
|
+
S->>M: the thread
|
|
57
|
+
M-->>B: an answer in plain words
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
It has two halves, one for each side of the chat.
|
|
61
|
+
|
|
62
|
+
### The server half
|
|
63
|
+
|
|
64
|
+
`@engenty/wizards/openui/server` draws nothing, so a server can import it alone.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { addWizard, loadWizards, wizardRules } from "@engenty/wizards/openui/server";
|
|
68
|
+
import { openuiChatLibrary, openuiChatPromptOptions } from "@openuidev/react-ui/genui-lib";
|
|
69
|
+
|
|
70
|
+
const wizards = await loadWizards("http://localhost:24368", ["<token>", "<token>"]);
|
|
71
|
+
const prompt = addWizard(openuiChatLibrary).prompt({
|
|
72
|
+
...openuiChatPromptOptions,
|
|
73
|
+
additionalRules: [...(openuiChatPromptOptions.additionalRules ?? []), ...wizardRules(wizards)],
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- `loadWizards(runtimeUrl, tokens)` reads each published wizard from the runtime
|
|
78
|
+
(`GET /api/public/wizards/:token`): its title, description and the fields its pages ask, in
|
|
79
|
+
order. A wizard the runtime does not answer for is left out, so the chat keeps working when
|
|
80
|
+
one is unpublished.
|
|
81
|
+
- `addWizard(library)` extends an OpenUI library with the Wizard component, among a Card’s
|
|
82
|
+
children. Its prompt then has `Wizard(wizard: string, note?: string, prefill?: …)`.
|
|
83
|
+
- `wizardRules(wizards)` are the rules that go with it: when to answer with a wizard, that the
|
|
84
|
+
wizard asks its own questions (never a Form in its place), what may be prefilled, and the list
|
|
85
|
+
of wizards with their tokens and fields.
|
|
86
|
+
|
|
87
|
+
With that, the model answers a fitting request with a Card that holds one short text and
|
|
88
|
+
`Wizard("<token>", "<note>", {prefill})`. The prefill holds answers the person already gave in
|
|
89
|
+
the conversation, by field id; the person still sees and sends each page.
|
|
90
|
+
|
|
91
|
+
### The component, in the browser
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import "@engenty/wizards/openui/styles.css";
|
|
95
|
+
import { addWizard, configureWizards, Wizard } from "@engenty/wizards/openui";
|
|
96
|
+
import { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
|
|
97
|
+
|
|
98
|
+
configureWizards({ runtime: "/wizards-runtime" });
|
|
99
|
+
const library = addWizard(openuiChatLibrary, Wizard);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- `configureWizards({ runtime })` names the runtime once, as the browser reaches it: a path the
|
|
103
|
+
host proxies to it, or the runtime’s address. A proxy on the host’s own address keeps the
|
|
104
|
+
runner’s visitor cookie first-party. `lang` sets the language of the runner’s own words
|
|
105
|
+
(`en` unless given), `Mascot` draws the wizard’s mascot above its pages.
|
|
106
|
+
- `addWizard(library, Wizard)` is the same extension as on the server, with the drawing
|
|
107
|
+
component. Both make the same prompt.
|
|
108
|
+
|
|
109
|
+
The component draws the run with the runner, the same code as the wizard’s own page
|
|
110
|
+
(`packages/runner`), in styles scoped to `.engenty-runner`, so the chat’s styles and the
|
|
111
|
+
runner’s never meet. Every field kind works as on the wizard’s own page, the camera and the
|
|
112
|
+
signature included. The page is not a frame, so nothing else is needed for them.
|
|
113
|
+
|
|
114
|
+
What happens in the message:
|
|
115
|
+
|
|
116
|
+
1. **The run starts** once the model’s line has finished streaming, so a half-written token never
|
|
117
|
+
starts a run: `POST /api/public/wizards/:token/runs`, as a visitor of the runtime.
|
|
118
|
+
2. **The run id stays with the message**, in the state OpenUI keeps for it. A message shown again
|
|
119
|
+
continues the same run.
|
|
120
|
+
3. **The run shows live** over the runtime’s stream of the run’s view (`/api/runs/:id/stream`), and
|
|
121
|
+
the person’s answers go to the run’s routes (`/api/runs/:id/pages/:step`, `…/reviews/:step`,
|
|
122
|
+
`…/back`, `…/retry`). These are the routes the wizard’s own page uses.
|
|
123
|
+
4. **The result goes back to the chat.** When the component sees the run finish, it sends OpenUI’s
|
|
124
|
+
`continue_conversation` action: a turn of the person that says the wizard finished, with the
|
|
125
|
+
result as context for the model: the wizard’s title, the run id and the texts of the result
|
|
126
|
+
steps, each cut at 4,000 characters. The model answers in plain words.
|
|
127
|
+
|
|
128
|
+
The chat hears of a run it saw finish. A message shown again with a done run shows the result
|
|
129
|
+
and tells the chat nothing new.
|
|
130
|
+
|
|
131
|
+
### Who runs, who pays
|
|
132
|
+
|
|
133
|
+
The browser talks to the runtime as a visitor, as on the wizard’s own page: the runtime sets a
|
|
134
|
+
visitor cookie, lets a visitor start 6 runs an hour
|
|
135
|
+
([`LIMIT_VISITOR_RUNS_PER_HOUR`](../../user/command-line.md#settings)) and spends the wizard’s own
|
|
136
|
+
credits or model keys. The chat’s model and the wizards’ model are two different things: the
|
|
137
|
+
chat picks the model that writes its answers, and each wizard’s steps run on what its space
|
|
138
|
+
has.
|
|
139
|
+
|
|
140
|
+
## Try it
|
|
141
|
+
|
|
142
|
+
`examples/openui-chat` is an OpenUI chat (`AgentInterface`) with any OpenAI-compatible model,
|
|
143
|
+
the wizards it may start and a proxy to the runtime. In short:
|
|
144
|
+
|
|
145
|
+
1. Start the runtime from a checkout (`pnpm dev`) and publish a wizard or two in the studio.
|
|
146
|
+
Each one’s token is the part of its link after `/w/`.
|
|
147
|
+
2. Put an `.env.local` in `examples/openui-chat`: `WIZARDS=<token>,<token>`, `CHAT_BASE_URL`,
|
|
148
|
+
`CHAT_API_KEY` and `CHAT_MODEL` for the chat’s model.
|
|
149
|
+
3. `pnpm --filter @engenty-wizards/example-openui-chat dev` and open `http://localhost:5190`.
|
|
150
|
+
4. Ask for something a wizard does, in your own words.
|
|
151
|
+
|
|
152
|
+
The example’s README has the details, the endpoints that work and what to set while you try
|
|
153
|
+
things.
|
|
154
|
+
|
|
155
|
+
## Exports
|
|
156
|
+
|
|
157
|
+
| From | Export | What it is |
|
|
158
|
+
|---|---|---|
|
|
159
|
+
| `@engenty/wizards/openui/server` | `loadWizards(runtimeUrl, tokens)` | The published wizards behind the tokens, as `WizardInfo[]` |
|
|
160
|
+
| | `wizardRules(wizards)` | The rules a system prompt adds |
|
|
161
|
+
| | `addWizard(library, component?)` | The library with the Wizard component among a Card’s children |
|
|
162
|
+
| | `WizardSpec`, `wizardProps`, `WizardProps` | The component as a prompt sees it, and its props |
|
|
163
|
+
| | `WIZARD_COMPONENT`, `WIZARD_DESCRIPTION` | Its name and description |
|
|
164
|
+
| `@engenty/wizards/openui` | all of the above | |
|
|
165
|
+
| | `configureWizards(config)` | Names the runtime, the language and the mascot |
|
|
166
|
+
| | `Wizard` | The drawing component |
|
|
167
|
+
| | `useWizardRun(runId, prefill)` | One run, live, for a host that draws runs itself |
|
|
168
|
+
| `@engenty/wizards/openui/styles.css` | | The runner’s styles, scoped to the wizard |
|
|
169
|
+
|
|
170
|
+
`@openuidev/react-lang`, `react`, `react-dom` and `zod` are peer dependencies: the chat brings
|
|
171
|
+
them. The package is written against `@openuidev/react-lang` 1.0 and the chat kit
|
|
172
|
+
`@openuidev/react-ui` 0.18.
|
|
173
|
+
|
|
174
|
+
## Good to know
|
|
175
|
+
|
|
176
|
+
- **One runtime per page.** `configureWizards` names it once, before the first render.
|
|
177
|
+
- **Other hosts.** The component sits on the runtime’s public run routes, not on OpenUI’s
|
|
178
|
+
internals. A host with its own components can draw a run with `useWizardRun` and the runner’s
|
|
179
|
+
parts, and another UI format can follow the same way.
|
|
180
|
+
- **OpenUI’s Inspect button** at the bottom right of a page in development is OpenUI’s own
|
|
181
|
+
(`@openuidev/react-lang` adds it and loads it from jsDelivr). A production build leaves it out.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Your own UI
|
|
3
|
+
description: Draw a wizard’s run in your own app with @engenty-wizards/runner and the runtime’s public run routes.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [OpenUI](./openui.md) shows one app that does it: it draws the run with
|
|
10
|
+
`@engenty-wizards/runner` (`packages/runner`) over the runtime’s public run routes.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Results to your systems
|
|
3
|
+
description: Send what a run produces to your own systems.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [Results, contacts, appointments](../../user/wordpress.md#results-contacts-appointments)
|
|
10
|
+
shows how the WordPress plugin receives results. A plugin can also answer other services with
|
|
11
|
+
its own [routes](../plugins/routes.md).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: WordPress
|
|
3
|
+
description: Put published wizards on a WordPress site with the plugin “engenty wizards”.
|
|
4
|
+
version: 0.7.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page is not written yet.
|
|
8
|
+
|
|
9
|
+
Until then, [WordPress](../../user/wordpress.md) in the user guide shows how you connect a site,
|
|
10
|
+
place a wizard and read its results in the admin.
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
"description": "Extend engenty wizards with plugins: tools for AI steps, routes with their own tables, pages in the studio.",
|
|
4
4
|
"root": true,
|
|
5
5
|
"icon": "SquareTerminal",
|
|
6
|
-
"pages": ["index", "wizard-format", "plugins"]
|
|
6
|
+
"pages": ["index", "wizard-format", "plugins", "integration"]
|
|
7
7
|
}
|
|
@@ -21,6 +21,7 @@ version: 0.5.0
|
|
|
21
21
|
| `wizards stop` | Stops it, with any other copy of it still running in the background. Your data is kept. AI apps that use your wizards start it again when you use one there |
|
|
22
22
|
| `wizards restart` | Stops it and starts it again; after an update, that is the new version. If it isn’t running, it starts in the background |
|
|
23
23
|
| `wizards update` | Installs the latest version |
|
|
24
|
+
| `wizards sandbox add` / `remove` | Adds the sandbox where AI steps run code, or removes it. It is agentOS, about 340 MB, and needs no Docker. Without a sandbox, steps can’t run code. `wizards sandbox` alone shows whether it is there. Name an engine to add another one: `wizards sandbox add agentos` |
|
|
24
25
|
| `wizards autostart on` / `off` | Starts it when you log in, or stops doing so. It is a LaunchAgent on macOS and a systemd user service on Linux |
|
|
25
26
|
| `wizards connect [app …]` | Adds your wizards to your [AI apps](./ai-apps.md): every app found, or the ones you name |
|
|
26
27
|
| `wizards disconnect [app …]` | Takes them out again |
|
|
@@ -51,6 +52,7 @@ running, `wizards start` opens the running one instead of starting a second.
|
|
|
51
52
|
| `~/.engenty/wizards/.env` | The settings file |
|
|
52
53
|
| `~/.engenty/wizards/plugins` | [Plugins](./plugins.md) on this computer |
|
|
53
54
|
| `~/.engenty/wizards/logs` | Logs: `install.log`, `update.log`, `runtime.log` when it runs in the background, `autostart.log` when a Mac starts it at login |
|
|
55
|
+
| `~/.engenty/wizards/engines` | The sandbox, once `wizards sandbox add` put it there: one folder per engine |
|
|
54
56
|
| `~/.engenty/wizards/tools`, `runtime` | Its own Node.js, and engenty wizards itself |
|
|
55
57
|
| `~/.engenty/wizards/bin/wizards` | The command; `~/.local/bin/wizards` links to it |
|
|
56
58
|
|
|
@@ -65,6 +67,7 @@ the studio doesn’t: one `NAME=value` per line. Restart engenty wizards after a
|
|
|
65
67
|
| `API_PORT` | The port | `24368`; if it is taken, the next free one up to `24387` |
|
|
66
68
|
| `CHROME_PATH` | The browser for PDF and PNG exports and steps on websites: Chrome, Edge, Chromium or Brave | The first one found: on a Mac Google Chrome, Microsoft Edge, Chromium or Brave in `/Applications` or `~/Applications`; on Linux `google-chrome`, `chromium`, `chromium-browser` or `microsoft-edge` on the PATH. `wizards status` names it |
|
|
67
69
|
| `FFMPEG_PATH` | ffmpeg for MP4 videos | `ffmpeg` |
|
|
70
|
+
| `SANDBOX_ALLOW_HOSTS` | Addresses the sandbox reaches besides the npm and PyPI registries, comma-separated: `api.example.com`. It reaches nothing else | not set |
|
|
68
71
|
| `OLLAMA_URL` | Where Ollama answers | `http://127.0.0.1:11434/v1` |
|
|
69
72
|
| `PLUGINS_DIR` | Folders with plugins, comma-separated. If you set it, it replaces the default | `~/.engenty/wizards/plugins` |
|
|
70
73
|
| `PLUGINS_WATCH` | With `0`, plugins no longer load again when their files change | `1` |
|
|
@@ -35,7 +35,7 @@ The logs show a link (“Open the studio: …”). Open it once: it signs your b
|
|
|
35
35
|
| Data | Databases and files are on the `/data` volume. Back that volume up |
|
|
36
36
|
| Models | Your own API keys or Ollama. The subscriptions of AI clients live on your own computer, not on a server |
|
|
37
37
|
| PDF, PNG, browser steps, MP4 | Chromium and ffmpeg are in the image |
|
|
38
|
-
| Code & shell | The sandbox is off in this image, so steps can’t use that tool. `compose.yaml` shows how to switch it on |
|
|
38
|
+
| Code & shell | The sandbox is off in this image, so steps can’t use that tool. `compose.yaml` shows how to switch it on: with Docker, or with agentOS built into the image |
|
|
39
39
|
| Plugins | Put them in a folder that you mount into the container and name in `PLUGINS_DIR` |
|
|
40
40
|
|
|
41
41
|
## Update
|
|
@@ -483,7 +483,7 @@ export async function runAgentStep(step, ctx) {
|
|
|
483
483
|
}
|
|
484
484
|
const resolved = await textModel(step.model ?? "high", { ...ctx.call, effort: step.effort });
|
|
485
485
|
const uploads = await personUploads(ctx);
|
|
486
|
-
const { tools, assets, close } = await buildStepTools(step, ctx, resolved, uploads);
|
|
486
|
+
const { tools, assets, instructions, close } = await buildStepTools(step, ctx, resolved, uploads);
|
|
487
487
|
// A step without tools of its own and without uploads: the run's device may answer it alone.
|
|
488
488
|
attachTools(resolved, tools, step.tools.length === 0 && uploads.length === 0);
|
|
489
489
|
try {
|
|
@@ -501,6 +501,7 @@ export async function runAgentStep(step, ctx) {
|
|
|
501
501
|
const system = [
|
|
502
502
|
groundRules(ctx),
|
|
503
503
|
step.tools.includes("browser") ? BROWSER_RULES : "",
|
|
504
|
+
instructions ?? "",
|
|
504
505
|
`Today is ${today(ctx)}.`,
|
|
505
506
|
brandBlock(ctx),
|
|
506
507
|
// Knowledge: what the space holds for its wizards, and how to find and read it.
|