@engenty/wizards-runtime 0.7.8 → 0.7.10
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 +2 -1
- package/apps/runtime/dist/app.js +2 -2
- package/apps/runtime/dist/cli/autostart.js +90 -7
- package/apps/runtime/dist/cli/autoupdate.js +18 -5
- package/apps/runtime/dist/cli/clients.js +25 -6
- package/apps/runtime/dist/cli/connect.js +7 -2
- package/apps/runtime/dist/cli/environment.js +33 -2
- package/apps/runtime/dist/cli/exec.js +38 -1
- package/apps/runtime/dist/cli/home.js +15 -0
- package/apps/runtime/dist/cli/machine.js +18 -8
- package/apps/runtime/dist/cli/processes.js +23 -3
- package/apps/runtime/dist/cli/setup.js +11 -1
- package/apps/runtime/dist/cli/start.js +33 -7
- package/apps/runtime/dist/cli/uninstall.js +100 -6
- package/apps/runtime/dist/cli/update.js +28 -12
- package/apps/runtime/dist/cli/versions.js +16 -4
- package/apps/runtime/dist/clients.js +118 -0
- package/apps/runtime/dist/db/client.js +37 -3
- package/apps/runtime/dist/db/migrations/tenant/0017_run_client.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0017_snapshot.json +3333 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +7 -0
- package/apps/runtime/dist/db/schema.js +2 -0
- package/apps/runtime/dist/docs/dev/api.md +39 -0
- package/apps/runtime/dist/docs/dev/index.md +1 -0
- package/apps/runtime/dist/docs/dev/integration/openui.md +5 -3
- package/apps/runtime/dist/docs/dev/meta.json +1 -1
- package/apps/runtime/dist/docs/user/ai-apps.md +14 -3
- package/apps/runtime/dist/docs/user/install.md +18 -8
- package/apps/runtime/dist/engine/runner.js +1 -0
- package/apps/runtime/dist/harness/env.js +41 -8
- package/apps/runtime/dist/harness/index.js +10 -1
- package/apps/runtime/dist/harness/model.js +1 -1
- package/apps/runtime/dist/index.js +13 -4
- package/apps/runtime/dist/plugin.js +24 -8
- package/apps/runtime/dist/render/browser-path.js +43 -11
- package/apps/runtime/dist/routes/runs.js +9 -0
- package/apps/runtime/dist/update.js +4 -0
- package/apps/web/dist/assets/AboutDialog-B2LuZ_mC.js +1 -0
- package/apps/web/dist/assets/ChangelogDialog-B0lS0BdL.js +1 -0
- package/apps/web/dist/assets/ChatView-BcPDcU2d.js +10 -0
- package/apps/web/dist/assets/EditorPage-erduYKNM.js +4 -0
- package/apps/web/dist/assets/{FlowPreview-Dx8AjXvE.js → FlowPreview-oX_Emm7u.js} +1 -1
- package/apps/web/dist/assets/{Harness-NvIb36TG.js → Harness-Dv9ln5xB.js} +2 -2
- package/apps/web/dist/assets/{NewWizardChannels-B2YgtJlt.js → NewWizardChannels-JveYyh-U.js} +1 -1
- package/apps/web/dist/assets/NewWizardPage-Dfk-WOhX.js +7 -0
- package/apps/web/dist/assets/OnboardingPage-CT9dL4ke.js +1 -0
- package/apps/web/dist/assets/ProjectPage-5_Wsk9Hv.js +1 -0
- package/apps/web/dist/assets/PublicRunner-Cw1WzTze.js +1 -0
- package/apps/web/dist/assets/{ReadOnly-CGNHlgUT.js → ReadOnly-S9vGVQHr.js} +1 -1
- package/apps/web/dist/assets/RunDrawer-O4rEFCL8.js +4 -0
- package/apps/web/dist/assets/RunnerView-BW1h4x63.js +1 -0
- package/apps/web/dist/assets/SettingsPage-DmhN7OTy.js +1 -0
- package/apps/web/dist/assets/SetupPage-BlWd7Uln.js +1 -0
- package/apps/web/dist/assets/{SharePage-hG7Z6SLy.js → SharePage-ktqm-jWI.js} +1 -1
- package/apps/web/dist/assets/changelog-FJJS0Tpt.js +1 -0
- package/apps/web/dist/assets/engenty-WpMi3xwq.js +1 -0
- package/apps/web/dist/assets/{esm-DVk3RJij.js → esm-C-ZWeuhU.js} +1 -1
- package/apps/web/dist/assets/{fluffy-engenty-ClRou7yu.js → fluffy-engenty-DPNHytrz.js} +135 -16
- package/apps/web/dist/assets/goose-helmet-Cvc7KjUg.bin +0 -0
- package/apps/web/dist/assets/goose-helmet-livery-CZD9u0XS.webp +0 -0
- package/apps/web/dist/assets/index-C4aHMcg9.css +1 -0
- package/apps/web/dist/assets/index-xH9uN8Nh.js +14 -0
- package/apps/web/dist/assets/oss-credits-Bc05Qv5H.js +1 -0
- package/apps/web/dist/assets/{phone-CXXHXYnA.js → phone-BjmhIKuT.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-DXzZCIMx.js → settings-menu-Dpkp3f56.js} +1 -1
- package/apps/web/dist/assets/{ui-DQ4L2npj.js → ui-DMmT-cSO.js} +4 -4
- package/apps/web/dist/assets/{upload-BnYHIfu5.js → upload-JX9BcMTq.js} +1 -1
- package/apps/web/dist/assets/{wrench-BrUJ7SV6.js → wrench-BSxnPs2_.js} +1 -1
- package/apps/web/dist/index.html +4 -4
- package/apps/web/dist/install.ps1 +307 -0
- package/apps/web/dist/mcp/flow.html +141 -22
- package/bin/wizards.mjs +59 -35
- package/node_modules/@engenty/wizards/package.json +1 -4
- package/node_modules/@engenty-wizards/shared/dist/claude-plugin.d.ts +7 -0
- package/node_modules/@engenty-wizards/shared/dist/claude-plugin.js +10 -0
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +2 -0
- package/node_modules/@engenty-wizards/shared/dist/run.js +4 -0
- package/package.json +2 -5
- package/plugin/.claude-plugin/plugin.json +28 -6
- package/plugin/README.md +58 -0
- package/plugin/hooks/engenty.ts +140 -0
- package/plugin/hooks/hooks.json +1 -0
- package/plugin/hooks/pane.test.tsx +177 -0
- package/plugin/hooks/register.tsx +396 -0
- package/plugin/types/index.d.ts +44 -0
- package/apps/web/dist/assets/AboutDialog-ByZyHXDj.js +0 -1
- package/apps/web/dist/assets/ChangelogDialog-QHYP0jAv.js +0 -1
- package/apps/web/dist/assets/ChatView-DupTtI8K.js +0 -10
- package/apps/web/dist/assets/EditorPage-k6qouLeS.js +0 -4
- package/apps/web/dist/assets/NewWizardPage-BgLY6SL6.js +0 -7
- package/apps/web/dist/assets/OnboardingPage-CxhwefJU.js +0 -1
- package/apps/web/dist/assets/ProjectPage-6ceSSS7W.js +0 -1
- package/apps/web/dist/assets/PublicRunner-6lQvReDx.js +0 -1
- package/apps/web/dist/assets/RunDrawer-TVGNnWyx.js +0 -4
- package/apps/web/dist/assets/RunnerView-DInSK0VZ.js +0 -1
- package/apps/web/dist/assets/SettingsPage-D3k5pXN5.js +0 -1
- package/apps/web/dist/assets/SetupPage-Bj5frdzY.js +0 -1
- package/apps/web/dist/assets/changelog-CO9vKjV0.js +0 -1
- package/apps/web/dist/assets/engenty-eXZ-EAwd.js +0 -1
- package/apps/web/dist/assets/index-DfaoPjNW.css +0 -1
- package/apps/web/dist/assets/index-DlDsr9Lc.js +0 -14
- package/apps/web/dist/assets/oss-credits-X2JPiMOR.js +0 -1
- package/node_modules/@engenty/wizards/dist/openui/Wizard.d.ts +0 -20
- package/node_modules/@engenty/wizards/dist/openui/Wizard.js +0 -62
- package/node_modules/@engenty/wizards/dist/openui/index.d.ts +0 -9
- package/node_modules/@engenty/wizards/dist/openui/index.js +0 -9
- package/node_modules/@engenty/wizards/dist/openui/message.d.ts +0 -11
- package/node_modules/@engenty/wizards/dist/openui/message.js +0 -69
- package/node_modules/@engenty/wizards/dist/openui/run.d.ts +0 -8
- package/node_modules/@engenty/wizards/dist/openui/run.js +0 -137
- package/node_modules/@engenty/wizards/dist/openui/server.d.ts +0 -37
- package/node_modules/@engenty/wizards/dist/openui/server.js +0 -77
- package/plugin/.mcp.json +0 -8
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var e={shared:[{name:`@engenty/wizards`,version:``,license:`Unknown`},{name:`@modelcontextprotocol/client`,version:`2.2.0`,license:`MIT`,homepage:`https://modelcontextprotocol.io`},{name:`@modelcontextprotocol/ext-apps`,version:`2.0.3`,license:`MIT`,homepage:`https://github.com/modelcontextprotocol/ext-apps`},{name:`dompurify`,version:`3.4.16`,license:`(MPL-2.0 OR Apache-2.0)`,homepage:`https://github.com/cure53/DOMPurify`},{name:`fflate`,version:`0.8.3`,license:`MIT`,homepage:`https://101arrowz.github.io/fflate`},{name:`lucide-react`,version:`1.49.0`,license:`ISC`,homepage:`https://lucide.dev`},{name:`marked`,version:`18.0.14`,license:`MIT`,homepage:`https://marked.js.org`},{name:`qr-scanner`,version:`1.4.2`,license:`MIT`,homepage:`https://github.com/nimiq/qr-scanner#readme`},{name:`zod`,version:`4.6.5`,license:`MIT`,homepage:`https://zod.dev`}],groups:[{id:`apps/runtime`,kind:`app`,label:`runtime`,packages:[{name:`@ai-sdk/anthropic`,version:`4.0.54`,license:`Apache-2.0`,homepage:`https://ai-sdk.dev/docs`},{name:`@ai-sdk/elevenlabs`,version:`3.0.42`,license:`Apache-2.0`,homepage:`https://ai-sdk.dev/docs`},{name:`@ai-sdk/fal`,version:`3.0.42`,license:`Apache-2.0`,homepage:`https://ai-sdk.dev/docs`},{name:`@ai-sdk/gateway`,version:`4.0.82`,license:`Apache-2.0`,homepage:`https://ai-sdk.dev/docs`},{name:`@ai-sdk/google`,version:`4.0.72`,license:`Apache-2.0`,homepage:`https://ai-sdk.dev/docs`},{name:`@ai-sdk/openai`,version:`4.0.67`,license:`Apache-2.0`,homepage:`https://ai-sdk.dev/docs`},{name:`@ai-sdk/replicate`,version:`3.0.42`,license:`Apache-2.0`,homepage:`https://ai-sdk.dev/docs`},{name:`@clack/prompts`,version:`1.8.1`,license:`MIT`,homepage:`https://github.com/bombshell-dev/clack/tree/main/packages/prompts#readme`},{name:`@executor-js/plugin-openapi`,version:`1.6.10`,license:`MIT`,homepage:`https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/openapi`},{name:`@hono/node-server`,version:`2.1.3`,license:`MIT`,homepage:`https://github.com/honojs/node-server`},{name:`@libsql/client`,version:`0.18.0`,license:`MIT`,homepage:`https://github.com/tursodatabase/libsql-client-ts#readme`},{name:`@mastra/core`,version:`1.77.0`,license:`Apache-2.0`,homepage:`https://mastra.ai`},{name:`@mastra/docker`,version:`0.8.0`,license:`Apache-2.0`,homepage:`https://mastra.ai`},{name:`@mastra/mcp`,version:`2.4.0`,license:`Apache-2.0`,homepage:`https://mastra.ai`},{name:`@mastra/quickjs`,version:`0.1.3`,license:`Apache-2.0`,homepage:`https://mastra.ai`},{name:`@modelcontextprotocol/server`,version:`2.2.0`,license:`MIT`,homepage:`https://modelcontextprotocol.io`},{name:`@napi-rs/canvas`,version:`0.1.80`,license:`MIT`,homepage:`https://github.com/Brooooooklyn/canvas#readme`},{name:`@turbodocx/html-to-docx`,version:`1.23.1`,license:`MIT`,homepage:`https://github.com/TurboDocx/html-to-docx#readme`},{name:`ai`,version:`7.0.102`,license:`Apache-2.0`,homepage:`https://ai-sdk.dev/docs`},{name:`aws4fetch`,version:`1.0.20`,license:`MIT`,homepage:`https://github.com/mhart/aws4fetch#readme`},{name:`drizzle-orm`,version:`0.45.3`,license:`Apache-2.0`,homepage:`https://orm.drizzle.team`},{name:`effect`,version:`4.0.0-beta.59`,license:`MIT`,homepage:`https://effect.website`},{name:`exceljs`,version:`4.4.0`,license:`MIT`,homepage:`https://github.com/exceljs/exceljs#readme`},{name:`fast-xml-parser`,version:`5.11.2`,license:`MIT`,homepage:`https://github.com/NaturalIntelligence/fast-xml-parser#readme`},{name:`hono`,version:`4.13.12`,license:`MIT`,homepage:`https://hono.dev`},{name:`imapflow`,version:`2.2.1`,license:`MIT`,homepage:`https://imapflow.com/`},{name:`jiti`,version:`2.7.0`,license:`MIT`,homepage:`https://github.com/unjs/jiti#readme`},{name:`jose`,version:`6.2.12`,license:`MIT`,homepage:`https://github.com/panva/jose`},{name:`mammoth`,version:`1.13.0`,license:`BSD-2-Clause`,homepage:`https://github.com/mwilliamson/mammoth.js#readme`},{name:`nanoid`,version:`5.1.16`,license:`MIT`,homepage:`https://github.com/ai/nanoid#readme`},{name:`node-pty`,version:`1.1.0`,license:`MIT`,homepage:`https://github.com/microsoft/node-pty`},{name:`pdf-parse`,version:`2.4.5`,license:`Apache-2.0`,homepage:`https://mehmet-kozan.github.io/pdf-parse/`},{name:`playwright-core`,version:`1.63.0`,license:`Apache-2.0`,homepage:`https://playwright.dev`},{name:`postal-mime`,version:`4.0.2`,license:`MIT-0`,homepage:`https://postal-mime.postalsys.com`},{name:`rfc6902`,version:`5.3.0`,license:`MIT`,homepage:`https://github.com/chbrown/rfc6902`},{name:`turndown`,version:`7.2.4`,license:`MIT`,homepage:`https://github.com/mixmark-io/turndown#readme`},{name:`undici`,version:`8.12.2`,license:`MIT`,homepage:`https://undici.nodejs.org`}]},{id:`apps/web`,kind:`app`,label:`web`,packages:[{name:`@dagrejs/dagre`,version:`3.1.1`,license:`MIT`,homepage:`https://github.com/dagrejs/dagre#readme`},{name:`@tanstack/react-query`,version:`5.104.0`,license:`MIT`,homepage:`https://tanstack.com/query`},{name:`@xterm/addon-fit`,version:`0.11.0`,license:`MIT`,homepage:`https://github.com/xtermjs/xterm.js/tree/master#readme`},{name:`@xterm/addon-web-links`,version:`0.12.0`,license:`MIT`,homepage:`https://github.com/xtermjs/xterm.js/tree/master#readme`},{name:`@xterm/xterm`,version:`6.0.0`,license:`MIT`,homepage:`https://github.com/xtermjs/xterm.js#readme`},{name:`@xyflow/react`,version:`12.12.0`,license:`MIT`,homepage:`https://reactflow.dev`},{name:`react`,version:`19.3.0`,license:`MIT`,homepage:`https://react.dev/`},{name:`react-dom`,version:`19.3.0`,license:`MIT`,homepage:`https://react.dev/`},{name:`react-router`,version:`7.18.4`,license:`MIT`,homepage:`https://github.com/remix-run/react-router#readme`},{name:`uqr`,version:`0.1.3`,license:`MIT`,homepage:`https://github.com/unjs/uqr#readme`}]},{id:`packages/runner`,kind:`package`,label:`runner`,packages:[{name:`pdfmake`,version:`0.3.11`,license:`MIT`,homepage:`http://pdfmake.org`}]}]};export{e as default};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { type Lang, type MascotProps } from "@engenty-wizards/runner";
|
|
2
|
-
export interface WizardsConfig {
|
|
3
|
-
/**
|
|
4
|
-
* Where the runtime answers, as the browser reaches it: a path the host proxies to it
|
|
5
|
-
* (`/wizards-runtime`, so the runner's cookie stays first-party) or the runtime's address.
|
|
6
|
-
*/
|
|
7
|
-
runtime: string;
|
|
8
|
-
/** The language of the runner's own words: `en` unless given. */
|
|
9
|
-
lang?: Lang;
|
|
10
|
-
/** The wizard's mascot above its pages; a plain dot in the wizard's colour unless given. */
|
|
11
|
-
Mascot?: (props: MascotProps) => React.ReactNode;
|
|
12
|
-
}
|
|
13
|
-
/** Names the runtime the Wizard component talks to. Once, before the first render. */
|
|
14
|
-
export declare function configureWizards(config: WizardsConfig): void;
|
|
15
|
-
/** The component an OpenUI library gets: `Wizard("<token>", "<note>", {prefill})`. */
|
|
16
|
-
export declare const Wizard: import("@openuidev/react-lang").DefinedComponent<import("zod").ZodObject<{
|
|
17
|
-
wizard: import("zod").ZodString;
|
|
18
|
-
note: import("zod").ZodOptional<import("zod").ZodString>;
|
|
19
|
-
prefill: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
20
|
-
}, import("zod/v4/core").$strip>>;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { api, configureRunner, RunnerBody, } from "@engenty-wizards/runner";
|
|
3
|
-
import { defineComponent } from "@openuidev/react-lang";
|
|
4
|
-
import { useEffect, useRef } from "react";
|
|
5
|
-
import { useMessageRun, useReport } from "./message.js";
|
|
6
|
-
import { useWizardRun } from "./run.js";
|
|
7
|
-
import { WIZARD_COMPONENT, WIZARD_DESCRIPTION, wizardProps } from "./server.js";
|
|
8
|
-
/** A plain stand-in for the studio's engenty. */
|
|
9
|
-
function Dot({ size = 64 }) {
|
|
10
|
-
const d = Math.min(size, 72);
|
|
11
|
-
return (_jsx("span", { "aria-hidden": "true", className: "inline-block rounded-full bg-ember", style: { width: d * 0.6, height: d * 0.6 } }));
|
|
12
|
-
}
|
|
13
|
-
/** Names the runtime the Wizard component talks to. Once, before the first render. */
|
|
14
|
-
export function configureWizards(config) {
|
|
15
|
-
const base = config.runtime.replace(/\/+$/, "");
|
|
16
|
-
configureRunner({
|
|
17
|
-
lang: config.lang ?? "en",
|
|
18
|
-
runBase: (runId) => `/api/runs/${runId}`,
|
|
19
|
-
withBase: (path) => `${base}${path}`,
|
|
20
|
-
asset: (path) => `${base}/${path.replace(/^\/+/, "")}`,
|
|
21
|
-
Mascot: config.Mascot ?? Dot,
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
/** Starts a run of the published wizard behind `token`, as a visitor of the runtime. */
|
|
25
|
-
const startRun = (token) => api
|
|
26
|
-
.post(`/api/public/wizards/${encodeURIComponent(token)}/runs`, {})
|
|
27
|
-
.then((started) => started.runId);
|
|
28
|
-
/** What the chat hears when a run is done: the result's texts, each cut short. */
|
|
29
|
-
function resultContext(view) {
|
|
30
|
-
const results = Object.entries(view.outputs)
|
|
31
|
-
.filter(([, out]) => typeof out.text === "string" && out.text.trim())
|
|
32
|
-
.map(([step, out]) => ({ step, text: (out.text ?? "").slice(0, 4000) }));
|
|
33
|
-
return { wizard: view.wizard.title, runId: view.id, results };
|
|
34
|
-
}
|
|
35
|
-
function WizardRun({ props }) {
|
|
36
|
-
const { runId, failed } = useMessageRun(props.wizard, startRun);
|
|
37
|
-
const run = useWizardRun(runId, props.prefill);
|
|
38
|
-
const report = useReport();
|
|
39
|
-
// The chat hears of a run it saw finish. A message shown again with a done run tells nothing.
|
|
40
|
-
const view = run.view;
|
|
41
|
-
const seenRunning = useRef(false);
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
if (!view) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
if (view.status !== "done") {
|
|
47
|
-
seenRunning.current = true;
|
|
48
|
-
}
|
|
49
|
-
else if (seenRunning.current) {
|
|
50
|
-
seenRunning.current = false;
|
|
51
|
-
report(`The wizard “${view.wizard.title}” finished.`, resultContext(view));
|
|
52
|
-
}
|
|
53
|
-
}, [view, report]);
|
|
54
|
-
return (_jsxs("div", { className: "engenty-runner overflow-hidden rounded-2xl border border-paper-3 bg-paper", children: [props.note ? _jsx("p", { className: "px-5 pt-4 text-[0.9375rem] text-ink-2", children: props.note }) : null, _jsx("div", { className: "px-5 pb-6", children: failed ? (_jsx("p", { className: "py-10 text-center text-ink-3", children: failed })) : (_jsx(RunnerBody, { run: run, compact: true })) })] }));
|
|
55
|
-
}
|
|
56
|
-
/** The component an OpenUI library gets: `Wizard("<token>", "<note>", {prefill})`. */
|
|
57
|
-
export const Wizard = defineComponent({
|
|
58
|
-
name: WIZARD_COMPONENT,
|
|
59
|
-
description: WIZARD_DESCRIPTION,
|
|
60
|
-
props: wizardProps,
|
|
61
|
-
component: ({ props }) => _jsx(WizardRun, { props: props }),
|
|
62
|
-
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wizards in OpenUI chats: the Wizard component runs a published wizard inside the chat, page
|
|
3
|
-
* by page, as its author defined it; the chat's model only decides that it runs and what it
|
|
4
|
-
* already knows. `server.ts` (`@engenty/wizards/openui/server`) is the server's half: the rules
|
|
5
|
-
* and the list of wizards.
|
|
6
|
-
*/
|
|
7
|
-
export { useWizardRun } from "./run.js";
|
|
8
|
-
export { addWizard, loadWizards, WIZARD_COMPONENT, WIZARD_DESCRIPTION, type WizardInfo, type WizardProps, WizardSpec, wizardProps, wizardRules, } from "./server.js";
|
|
9
|
-
export { configureWizards, Wizard, type WizardsConfig } from "./Wizard.js";
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wizards in OpenUI chats: the Wizard component runs a published wizard inside the chat, page
|
|
3
|
-
* by page, as its author defined it; the chat's model only decides that it runs and what it
|
|
4
|
-
* already knows. `server.ts` (`@engenty/wizards/openui/server`) is the server's half: the rules
|
|
5
|
-
* and the list of wizards.
|
|
6
|
-
*/
|
|
7
|
-
export { useWizardRun } from "./run.js";
|
|
8
|
-
export { addWizard, loadWizards, WIZARD_COMPONENT, WIZARD_DESCRIPTION, WizardSpec, wizardProps, wizardRules, } from "./server.js";
|
|
9
|
-
export { configureWizards, Wizard } from "./Wizard.js";
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The run this message shows: the one it kept, else a new one from `start`. A run starts once
|
|
3
|
-
* the reply has finished streaming, as the token can be half written until then, and once per
|
|
4
|
-
* message, however often React runs the effect (twice in Strict Mode).
|
|
5
|
-
*/
|
|
6
|
-
export declare function useMessageRun(token: string | undefined, start: (token: string) => Promise<string>): {
|
|
7
|
-
runId: string | null;
|
|
8
|
-
failed: string | null;
|
|
9
|
-
};
|
|
10
|
-
/** Tells the chat something as a turn of the person, with `context` for the model. */
|
|
11
|
-
export declare function useReport(): (message: string, context: unknown) => void;
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { useGetFieldValue, useIsStreaming, useSetFieldValue, useTriggerAction, } from "@openuidev/react-lang";
|
|
2
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
-
import { WIZARD_COMPONENT } from "./server.js";
|
|
4
|
-
/**
|
|
5
|
-
* What the Wizard component keeps with its message, in OpenUI's state of the message.
|
|
6
|
-
*
|
|
7
|
-
* OpenUI keeps that state as the fields of forms, saves it with the message and restores it when
|
|
8
|
-
* the message is shown again. An action hands the chat the fields of the form it names, or every
|
|
9
|
-
* field where it names none; the chat shows them as “Form data” and gives them to the model. So
|
|
10
|
-
* the run id is a field of its own, which no action names, and the action that reports the
|
|
11
|
-
* result names a form that holds nothing.
|
|
12
|
-
*/
|
|
13
|
-
const runField = (token) => `wizard:${token}`;
|
|
14
|
-
const EMPTY_FORM = "wizard:empty";
|
|
15
|
-
/**
|
|
16
|
-
* The run this message shows: the one it kept, else a new one from `start`. A run starts once
|
|
17
|
-
* the reply has finished streaming, as the token can be half written until then, and once per
|
|
18
|
-
* message, however often React runs the effect (twice in Strict Mode).
|
|
19
|
-
*/
|
|
20
|
-
export function useMessageRun(token, start) {
|
|
21
|
-
const streaming = useIsStreaming();
|
|
22
|
-
const getField = useGetFieldValue();
|
|
23
|
-
const setField = useSetFieldValue();
|
|
24
|
-
const [runId, setRunId] = useState(null);
|
|
25
|
-
const [failed, setFailed] = useState(null);
|
|
26
|
-
const started = useRef(null);
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (streaming || runId || failed || !token) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
let cancelled = false;
|
|
32
|
-
const take = async () => {
|
|
33
|
-
// OpenUI restores the message's state in an effect of its own, which runs after this one.
|
|
34
|
-
await Promise.resolve();
|
|
35
|
-
if (cancelled) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const kept = getField(undefined, runField(token));
|
|
39
|
-
if (typeof kept === "string") {
|
|
40
|
-
setRunId(kept);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
started.current ??= start(token);
|
|
44
|
-
const id = await started.current;
|
|
45
|
-
if (!cancelled) {
|
|
46
|
-
setRunId(id);
|
|
47
|
-
setField(undefined, WIZARD_COMPONENT, runField(token), id, true);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
take().catch((err) => {
|
|
51
|
-
if (!cancelled) {
|
|
52
|
-
setFailed(err instanceof Error ? err.message : String(err));
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
return () => {
|
|
56
|
-
cancelled = true;
|
|
57
|
-
};
|
|
58
|
-
}, [streaming, runId, failed, token, getField, setField, start]);
|
|
59
|
-
return { runId, failed };
|
|
60
|
-
}
|
|
61
|
-
/** Tells the chat something as a turn of the person, with `context` for the model. */
|
|
62
|
-
export function useReport() {
|
|
63
|
-
const setField = useSetFieldValue();
|
|
64
|
-
const trigger = useTriggerAction();
|
|
65
|
-
return useCallback((message, context) => {
|
|
66
|
-
setField(EMPTY_FORM, undefined, "empty", undefined, false);
|
|
67
|
-
void trigger(message, EMPTY_FORM, { type: "continue_conversation", params: { context } });
|
|
68
|
-
}, [setField, trigger]);
|
|
69
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type RunSource } from "@engenty-wizards/runner";
|
|
2
|
-
/**
|
|
3
|
-
* One run, live: the runtime's stream of the whole view, plus the commands a person gives. The
|
|
4
|
-
* same as the studio's `useRun` (apps/web/src/runner/useRun.ts), on the runner's own client, so
|
|
5
|
-
* it talks to whichever runtime `configureWizards` named. `prefill` starts a page's fields with
|
|
6
|
-
* answers the chat already knows; the person still sees and sends the page.
|
|
7
|
-
*/
|
|
8
|
-
export declare function useWizardRun(runId: string | null, prefill: Record<string, unknown> | undefined): RunSource;
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { ApiError, api, runnerEnv, setChoiceLabels } from "@engenty-wizards/runner";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
|
-
/** Two missed pings: the stream is taken for dead. */
|
|
4
|
-
const STALE_MS = 45_000;
|
|
5
|
-
/**
|
|
6
|
-
* One run, live: the runtime's stream of the whole view, plus the commands a person gives. The
|
|
7
|
-
* same as the studio's `useRun` (apps/web/src/runner/useRun.ts), on the runner's own client, so
|
|
8
|
-
* it talks to whichever runtime `configureWizards` named. `prefill` starts a page's fields with
|
|
9
|
-
* answers the chat already knows; the person still sees and sends the page.
|
|
10
|
-
*/
|
|
11
|
-
export function useWizardRun(runId, prefill) {
|
|
12
|
-
const [view, setView] = useState(null);
|
|
13
|
-
const [error, setError] = useState(null);
|
|
14
|
-
const [notFound, setNotFound] = useState(false);
|
|
15
|
-
const [busy, setBusy] = useState(false);
|
|
16
|
-
const [fieldErrors, setFieldErrors] = useState({});
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
setView(null);
|
|
19
|
-
setNotFound(false);
|
|
20
|
-
if (!runId) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
const { runBase, withBase } = runnerEnv();
|
|
24
|
-
let stopped = false;
|
|
25
|
-
let retry = 0;
|
|
26
|
-
let timer;
|
|
27
|
-
let es = null;
|
|
28
|
-
let lastHeard = Date.now();
|
|
29
|
-
const refresh = async () => {
|
|
30
|
-
try {
|
|
31
|
-
const fresh = await api.get(runBase(runId));
|
|
32
|
-
if (!stopped) {
|
|
33
|
-
setView(fresh);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
catch (err) {
|
|
37
|
-
if (err instanceof ApiError && err.status === 404) {
|
|
38
|
-
stopped = true;
|
|
39
|
-
es?.close();
|
|
40
|
-
setNotFound(true);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const open = () => {
|
|
45
|
-
clearTimeout(timer);
|
|
46
|
-
es?.close();
|
|
47
|
-
if (stopped) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const stream = new EventSource(withBase(`${runBase(runId)}/stream`), {
|
|
51
|
-
withCredentials: true,
|
|
52
|
-
});
|
|
53
|
-
es = stream;
|
|
54
|
-
lastHeard = Date.now();
|
|
55
|
-
stream.addEventListener("view", (e) => {
|
|
56
|
-
retry = 0;
|
|
57
|
-
lastHeard = Date.now();
|
|
58
|
-
setView(JSON.parse(e.data));
|
|
59
|
-
});
|
|
60
|
-
stream.addEventListener("ping", () => {
|
|
61
|
-
lastHeard = Date.now();
|
|
62
|
-
});
|
|
63
|
-
stream.onerror = () => {
|
|
64
|
-
stream.close();
|
|
65
|
-
if (stopped || es !== stream) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
es = null;
|
|
69
|
-
void refresh();
|
|
70
|
-
retry = Math.min(retry + 1, 6);
|
|
71
|
-
timer = setTimeout(open, 500 * 2 ** retry);
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
|
-
const watchdog = setInterval(() => {
|
|
75
|
-
if (!stopped && es && Date.now() - lastHeard > STALE_MS) {
|
|
76
|
-
retry = 0;
|
|
77
|
-
open();
|
|
78
|
-
}
|
|
79
|
-
}, 15_000);
|
|
80
|
-
open();
|
|
81
|
-
return () => {
|
|
82
|
-
stopped = true;
|
|
83
|
-
clearTimeout(timer);
|
|
84
|
-
clearInterval(watchdog);
|
|
85
|
-
es?.close();
|
|
86
|
-
};
|
|
87
|
-
}, [runId]);
|
|
88
|
-
const command = useCallback(async (path, body) => {
|
|
89
|
-
if (!runId) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
setBusy(true);
|
|
93
|
-
setError(null);
|
|
94
|
-
setFieldErrors({});
|
|
95
|
-
try {
|
|
96
|
-
await api.post(`${runnerEnv().runBase(runId)}/${path}`, body);
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
catch (err) {
|
|
100
|
-
if (err instanceof ApiError && err.status === 422 && Array.isArray(err.body?.fields)) {
|
|
101
|
-
setFieldErrors(Object.fromEntries(err.body.fields.map((f) => [f.field, f.message])));
|
|
102
|
-
}
|
|
103
|
-
setError(err.message);
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
finally {
|
|
107
|
-
setBusy(false);
|
|
108
|
-
}
|
|
109
|
-
}, [runId]);
|
|
110
|
-
// The chat's answers start the page's fields, under what the run already holds.
|
|
111
|
-
const shown = useMemo(() => {
|
|
112
|
-
if (!view || !prefill || view.step?.type !== "page") {
|
|
113
|
-
return view;
|
|
114
|
-
}
|
|
115
|
-
const known = Object.fromEntries(view.step.fields.filter((f) => f.id in prefill).map((f) => [f.id, prefill[f.id]]));
|
|
116
|
-
return Object.keys(known).length ? { ...view, prefill: { ...known, ...view.prefill } } : view;
|
|
117
|
-
}, [view, prefill]);
|
|
118
|
-
setChoiceLabels(view?.translation?.labels);
|
|
119
|
-
return {
|
|
120
|
-
view: shown,
|
|
121
|
-
notFound,
|
|
122
|
-
error,
|
|
123
|
-
busy,
|
|
124
|
-
fieldErrors,
|
|
125
|
-
submitPage: (stepId, values) => command(`pages/${stepId}`, { values }),
|
|
126
|
-
accept: (stepId, edits) => command(`reviews/${stepId}`, { type: "accept", edits }),
|
|
127
|
-
regenerate: (stepId, target, note, items) => command(`reviews/${stepId}`, {
|
|
128
|
-
type: "regenerate",
|
|
129
|
-
target,
|
|
130
|
-
note,
|
|
131
|
-
items: items?.length ? items : undefined,
|
|
132
|
-
}),
|
|
133
|
-
back: () => command("back"),
|
|
134
|
-
retry: () => command("retry"),
|
|
135
|
-
translateResult: (stepId) => command("translate-result", { stepId }),
|
|
136
|
-
};
|
|
137
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { PublicField } from "@engenty-wizards/shared/run";
|
|
2
|
-
import { type Library } from "@openuidev/react-lang";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
/**
|
|
5
|
-
* The model's half of the Wizard component: its props, its description and the rules a system
|
|
6
|
-
* prompt gets. Nothing here draws, so a chat server builds its prompt from this file alone.
|
|
7
|
-
*/
|
|
8
|
-
export declare const WIZARD_COMPONENT = "Wizard";
|
|
9
|
-
export declare const wizardProps: z.ZodObject<{
|
|
10
|
-
wizard: z.ZodString;
|
|
11
|
-
note: z.ZodOptional<z.ZodString>;
|
|
12
|
-
prefill: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
13
|
-
}, z.core.$strip>;
|
|
14
|
-
export type WizardProps = z.infer<typeof wizardProps>;
|
|
15
|
-
export declare const WIZARD_DESCRIPTION = "Runs a predefined wizard inline: its pages, AI steps, review and result, exactly as its author defined them. Use it whenever a listed wizard fits the request; never rebuild a wizard's pages with Form components.";
|
|
16
|
-
/** The component as a prompt sees it: the same name and props, nothing to draw. */
|
|
17
|
-
export declare const WizardSpec: import("@openuidev/react-lang").DefinedComponent<z.ZodObject<{
|
|
18
|
-
wizard: z.ZodString;
|
|
19
|
-
note: z.ZodOptional<z.ZodString>;
|
|
20
|
-
prefill: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
21
|
-
}, z.core.$strip>>;
|
|
22
|
-
/**
|
|
23
|
-
* The library with the Wizard component among a Card's children. A server passes `WizardSpec`
|
|
24
|
-
* for its prompt, the browser the drawing `Wizard`; both make the same prompt.
|
|
25
|
-
*/
|
|
26
|
-
export declare function addWizard<L extends Library>(library: L, component?: typeof WizardSpec): Library;
|
|
27
|
-
/** A wizard as the chat server lists it to the model. */
|
|
28
|
-
export interface WizardInfo {
|
|
29
|
-
token: string;
|
|
30
|
-
title: string;
|
|
31
|
-
description: string;
|
|
32
|
-
fields: PublicField[];
|
|
33
|
-
}
|
|
34
|
-
/** Reads the published wizards behind these tokens from a runtime; ones it cannot read are left out. */
|
|
35
|
-
export declare function loadWizards(runtimeUrl: string, tokens: string[]): Promise<WizardInfo[]>;
|
|
36
|
-
/** The rules a system prompt adds for the Wizard component: when to use it and which wizards exist. */
|
|
37
|
-
export declare function wizardRules(wizards: WizardInfo[]): string[];
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { defineComponent } from "@openuidev/react-lang";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
/**
|
|
4
|
-
* The model's half of the Wizard component: its props, its description and the rules a system
|
|
5
|
-
* prompt gets. Nothing here draws, so a chat server builds its prompt from this file alone.
|
|
6
|
-
*/
|
|
7
|
-
export const WIZARD_COMPONENT = "Wizard";
|
|
8
|
-
export const wizardProps = z.object({
|
|
9
|
-
wizard: z.string().describe("The token of a wizard from the list of available wizards"),
|
|
10
|
-
note: z
|
|
11
|
-
.string()
|
|
12
|
-
.optional()
|
|
13
|
-
.describe("One short sentence shown above the wizard: why it starts now"),
|
|
14
|
-
prefill: z
|
|
15
|
-
.record(z.string(), z.unknown())
|
|
16
|
-
.optional()
|
|
17
|
-
.describe("Answers already known from the conversation, by field id; the person still checks them"),
|
|
18
|
-
});
|
|
19
|
-
export const WIZARD_DESCRIPTION = "Runs a predefined wizard inline: its pages, AI steps, review and result, exactly as its author defined them. Use it whenever a listed wizard fits the request; never rebuild a wizard's pages with Form components.";
|
|
20
|
-
/** The component as a prompt sees it: the same name and props, nothing to draw. */
|
|
21
|
-
export const WizardSpec = defineComponent({
|
|
22
|
-
name: WIZARD_COMPONENT,
|
|
23
|
-
description: WIZARD_DESCRIPTION,
|
|
24
|
-
props: wizardProps,
|
|
25
|
-
component: () => null,
|
|
26
|
-
});
|
|
27
|
-
/**
|
|
28
|
-
* The library with the Wizard component among a Card's children. A server passes `WizardSpec`
|
|
29
|
-
* for its prompt, the browser the drawing `Wizard`; both make the same prompt.
|
|
30
|
-
*/
|
|
31
|
-
export function addWizard(library, component = WizardSpec) {
|
|
32
|
-
if (!library.extend) {
|
|
33
|
-
throw new Error("This OpenUI library cannot be extended.");
|
|
34
|
-
}
|
|
35
|
-
return library.extend({ components: { add: [{ component, slots: ["Card"] }] } });
|
|
36
|
-
}
|
|
37
|
-
/** Reads the published wizards behind these tokens from a runtime; ones it cannot read are left out. */
|
|
38
|
-
export async function loadWizards(runtimeUrl, tokens) {
|
|
39
|
-
const base = runtimeUrl.replace(/\/+$/, "");
|
|
40
|
-
const found = await Promise.all(tokens.map(async (token) => {
|
|
41
|
-
try {
|
|
42
|
-
const res = await fetch(`${base}/api/public/wizards/${encodeURIComponent(token)}`);
|
|
43
|
-
if (!res.ok) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const w = (await res.json());
|
|
47
|
-
return w.available
|
|
48
|
-
? { token: w.token, title: w.title, description: w.description, fields: w.fields ?? [] }
|
|
49
|
-
: null;
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}));
|
|
55
|
-
return found.filter((w) => w !== null);
|
|
56
|
-
}
|
|
57
|
-
function fieldLine(f) {
|
|
58
|
-
const choices = f.options?.length
|
|
59
|
-
? ` one of ${f.options.map((o) => JSON.stringify(o)).join(" | ")}`
|
|
60
|
-
: "";
|
|
61
|
-
return `${f.id} (${f.kind}${choices}${f.required ? ", required" : ""}): ${f.label}`;
|
|
62
|
-
}
|
|
63
|
-
/** The rules a system prompt adds for the Wizard component: when to use it and which wizards exist. */
|
|
64
|
-
export function wizardRules(wizards) {
|
|
65
|
-
if (!wizards.length) {
|
|
66
|
-
return [];
|
|
67
|
-
}
|
|
68
|
-
const list = wizards
|
|
69
|
-
.map((w) => `- "${w.title}" token: ${w.token} — ${w.description}\n fields: ${w.fields.map(fieldLine).join("; ") || "none"}`)
|
|
70
|
-
.join("\n");
|
|
71
|
-
return [
|
|
72
|
-
`Wizards are fixed workflows with their own pages, AI steps and results. When the person asks for something a wizard below does, answer with a Card that holds one short TextContent and Wizard("<token>", "<note>", {prefill}). Do not ask the wizard's questions yourself and do not build them as a Form: the wizard asks them.`,
|
|
73
|
-
`Prefill only answers the person has actually given in this conversation, by field id; leave out anything you would have to guess. Dates are YYYY-MM-DD.`,
|
|
74
|
-
`When a message says a wizard finished, its context holds the result: answer in plain words about it, and start a wizard again only when asked.`,
|
|
75
|
-
`Available wizards:\n${list}`,
|
|
76
|
-
];
|
|
77
|
-
}
|