@engenty/wizards 0.8.0 → 0.9.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":["WIZARD_COMPONENT","wizardProps","z","WIZARD_DESCRIPTION","WizardSpec","defineComponent","addWizard","library","loadWizards","base","runtimeUrl","tokens","res","token","w","fieldLine","choices","f","o","wizardRules","wizards"],"sources":["../../src/openui/server.ts"],"sourcesContent":["import type { PublicField, PublicWizard } from \"@engenty-wizards/shared/run\";\nimport { defineComponent, type Library } from \"@openuidev/react-lang\";\nimport { z } from \"zod\";\n\n/**\n * The model's half of the Wizard component: its props, its description and the rules a system\n * prompt gets. Nothing here draws, so a chat server builds its prompt from this file alone.\n */\n\nexport const WIZARD_COMPONENT = \"Wizard\";\n\nexport const wizardProps = z.object({\n wizard: z.string().describe(\"The token of a wizard from the list of available wizards\"),\n note: z\n .string()\n .optional()\n .describe(\"One short sentence shown above the wizard: why it starts now\"),\n prefill: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Answers already known from the conversation, by field id; the person still checks them\",\n ),\n});\n\nexport type WizardProps = z.infer<typeof wizardProps>;\n\nexport const WIZARD_DESCRIPTION =\n \"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.\";\n\n/** The component as a prompt sees it: the same name and props, nothing to draw. */\nexport const WizardSpec = defineComponent({\n name: WIZARD_COMPONENT,\n description: WIZARD_DESCRIPTION,\n props: wizardProps,\n component: () => null,\n});\n\n/**\n * The library with the Wizard component among a Card's children. A server passes `WizardSpec`\n * for its prompt, the browser the drawing `Wizard`; both make the same prompt.\n */\nexport function addWizard<L extends Library>(\n library: L,\n component: typeof WizardSpec = WizardSpec,\n): Library {\n if (!library.extend) {\n throw new Error(\"This OpenUI library cannot be extended.\");\n }\n return library.extend({ components: { add: [{ component, slots: [\"Card\"] }] } });\n}\n\n/** A wizard as the chat server lists it to the model. */\nexport interface WizardInfo {\n token: string;\n title: string;\n description: string;\n fields: PublicField[];\n}\n\n/** Reads the published wizards behind these tokens from a runtime; ones it cannot read are left out. */\nexport async function loadWizards(runtimeUrl: string, tokens: string[]): Promise<WizardInfo[]> {\n const base = runtimeUrl.replace(/\\/+$/, \"\");\n const found = await Promise.all(\n tokens.map(async (token) => {\n try {\n const res = await fetch(`${base}/api/public/wizards/${encodeURIComponent(token)}`);\n if (!res.ok) {\n return null;\n }\n const w = (await res.json()) as PublicWizard;\n return w.available\n ? { token: w.token, title: w.title, description: w.description, fields: w.fields ?? [] }\n : null;\n } catch {\n return null;\n }\n }),\n );\n return found.filter((w): w is WizardInfo => w !== null);\n}\n\nfunction fieldLine(f: PublicField): string {\n const choices = f.options?.length\n ? ` one of ${f.options.map((o) => JSON.stringify(o)).join(\" | \")}`\n : \"\";\n return `${f.id} (${f.kind}${choices}${f.required ? \", required\" : \"\"}): ${f.label}`;\n}\n\n/** The rules a system prompt adds for the Wizard component: when to use it and which wizards exist. */\nexport function wizardRules(wizards: WizardInfo[]): string[] {\n if (!wizards.length) {\n return [];\n }\n const list = wizards\n .map(\n (w) =>\n `- \"${w.title}\" token: ${w.token} — ${w.description}\\n fields: ${w.fields.map(fieldLine).join(\"; \") || \"none\"}`,\n )\n .join(\"\\n\");\n return [\n `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.`,\n `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.`,\n `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.`,\n `Available wizards:\\n${list}`,\n ];\n}\n"],"mappings":";;;AASA,IAAaA,IAAmB,UAEnBC,IAAcC,EAAE,OAAO;CAClC,QAAQA,EAAE,OAAO,CAAC,CAAC,SAAS,0DAA0D;CACtF,MAAMA,EACH,OAAO,CAAC,CACR,SAAS,CAAC,CACV,SAAS,8DAA8D;CAC1E,SAASA,EACN,OAAOA,EAAE,OAAO,GAAGA,EAAE,QAAQ,CAAC,CAAC,CAC/B,SAAS,CAAC,CACV,SACC,wFACF;AACJ,CAAC,GAIYC,IACX,uNAGWC,IAAaC,EAAgB;CACxC,MAAML;CACN,aAAaG;CACb,OAAOF;CACP,iBAAiB;AACnB,CAAC;AAMD,SAAgBK,EACd,GACA,IAA+BF,GACtB;CACT,IAAI,CAACG,EAAQ,QACX,MAAU,MAAM,yCAAyC;CAE3D,OAAOA,EAAQ,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC;EAAE;EAAW,OAAO,CAAC,MAAM;CAAE,CAAC,EAAE,EAAE,CAAC;AACjF;AAWA,eAAsBC,EAAY,GAAoB,GAAyC;CAC7F,IAAMC,IAAOC,EAAW,QAAQ,QAAQ,EAAE;CAiB1C,QAAO,MAhBa,QAAQ,IAC1BC,EAAO,IAAI,OAAO,MAAU;EAC1B,IAAI;GACF,IAAMC,IAAM,MAAM,MAAM,GAAGH,EAAK,sBAAsB,mBAAmBI,CAAK,GAAG;GACjF,IAAI,CAACD,EAAI,IACP,OAAO;GAET,IAAME,IAAK,MAAMF,EAAI,KAAK;GAC1B,OAAOE,EAAE,YACL;IAAE,OAAOA,EAAE;IAAO,OAAOA,EAAE;IAAO,aAAaA,EAAE;IAAa,QAAQA,EAAE,UAAU,CAAC;GAAE,IACrF;EACN,QAAQ;GACN,OAAO;EACT;CACF,CAAC,CACH,EAAA,CACa,QAAQ,MAAuBA,MAAM,IAAI;AACxD;AAEA,SAASC,EAAU,GAAwB;CACzC,IAAMC,IAAUC,EAAE,SAAS,SACvB,WAAWA,EAAE,QAAQ,KAAK,MAAM,KAAK,UAAUC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,MAC7D;CACJ,OAAO,GAAGD,EAAE,GAAG,IAAIA,EAAE,OAAOD,IAAUC,EAAE,WAAW,eAAe,GAAG,KAAKA,EAAE;AAC9E;AAGA,SAAgBE,EAAY,GAAiC;CAU3D,OATKC,EAAQ,SASN;EACL;EACA;EACA;EACA,uBAVWA,EACV,KACE,MACC,MAAMN,EAAE,MAAM,WAAWA,EAAE,MAAM,KAAKA,EAAE,YAAY,cAAcA,EAAE,OAAO,IAAIC,CAAS,CAAC,CAAC,KAAK,IAAI,KAAK,QAC5G,CAAC,CACA,KAAK,IAKiB;CACzB,IAbS,CAAC;AAcZ"}
1
+ {"version":3,"file":"server.js","names":["WIZARD_COMPONENT","wizardProps","z","WIZARD_DESCRIPTION","WizardSpec","defineComponent","addWizard","library","loadWizards","base","runtimeUrl","tokens","res","token","w","fieldLine","choices","f","o","wizardRules","wizards"],"sources":["../../src/openui/server.ts"],"sourcesContent":["import type { PublicField, PublicWizard } from \"@engenty/wizards-shared/run\";\nimport { defineComponent, type Library } from \"@openuidev/react-lang\";\nimport { z } from \"zod\";\n\n/**\n * The model's half of the Wizard component: its props, its description and the rules a system\n * prompt gets. Nothing here draws, so a chat server builds its prompt from this file alone.\n */\n\nexport const WIZARD_COMPONENT = \"Wizard\";\n\nexport const wizardProps = z.object({\n wizard: z.string().describe(\"The token of a wizard from the list of available wizards\"),\n note: z\n .string()\n .optional()\n .describe(\"One short sentence shown above the wizard: why it starts now\"),\n prefill: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Answers already known from the conversation, by field id; the person still checks them\",\n ),\n});\n\nexport type WizardProps = z.infer<typeof wizardProps>;\n\nexport const WIZARD_DESCRIPTION =\n \"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.\";\n\n/** The component as a prompt sees it: the same name and props, nothing to draw. */\nexport const WizardSpec = defineComponent({\n name: WIZARD_COMPONENT,\n description: WIZARD_DESCRIPTION,\n props: wizardProps,\n component: () => null,\n});\n\n/**\n * The library with the Wizard component among a Card's children. A server passes `WizardSpec`\n * for its prompt, the browser the drawing `Wizard`; both make the same prompt.\n */\nexport function addWizard<L extends Library>(\n library: L,\n component: typeof WizardSpec = WizardSpec,\n): Library {\n if (!library.extend) {\n throw new Error(\"This OpenUI library cannot be extended.\");\n }\n return library.extend({ components: { add: [{ component, slots: [\"Card\"] }] } });\n}\n\n/** A wizard as the chat server lists it to the model. */\nexport interface WizardInfo {\n token: string;\n title: string;\n description: string;\n fields: PublicField[];\n}\n\n/** Reads the published wizards behind these tokens from a runtime; ones it cannot read are left out. */\nexport async function loadWizards(runtimeUrl: string, tokens: string[]): Promise<WizardInfo[]> {\n const base = runtimeUrl.replace(/\\/+$/, \"\");\n const found = await Promise.all(\n tokens.map(async (token) => {\n try {\n const res = await fetch(`${base}/api/public/wizards/${encodeURIComponent(token)}`);\n if (!res.ok) {\n return null;\n }\n const w = (await res.json()) as PublicWizard;\n return w.available\n ? { token: w.token, title: w.title, description: w.description, fields: w.fields ?? [] }\n : null;\n } catch {\n return null;\n }\n }),\n );\n return found.filter((w): w is WizardInfo => w !== null);\n}\n\nfunction fieldLine(f: PublicField): string {\n const choices = f.options?.length\n ? ` one of ${f.options.map((o) => JSON.stringify(o)).join(\" | \")}`\n : \"\";\n return `${f.id} (${f.kind}${choices}${f.required ? \", required\" : \"\"}): ${f.label}`;\n}\n\n/** The rules a system prompt adds for the Wizard component: when to use it and which wizards exist. */\nexport function wizardRules(wizards: WizardInfo[]): string[] {\n if (!wizards.length) {\n return [];\n }\n const list = wizards\n .map(\n (w) =>\n `- \"${w.title}\" token: ${w.token} — ${w.description}\\n fields: ${w.fields.map(fieldLine).join(\"; \") || \"none\"}`,\n )\n .join(\"\\n\");\n return [\n `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.`,\n `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.`,\n `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.`,\n `Available wizards:\\n${list}`,\n ];\n}\n"],"mappings":";;;AASA,IAAaA,IAAmB,UAEnBC,IAAcC,EAAE,OAAO;CAClC,QAAQA,EAAE,OAAO,CAAC,CAAC,SAAS,0DAA0D;CACtF,MAAMA,EACH,OAAO,CAAC,CACR,SAAS,CAAC,CACV,SAAS,8DAA8D;CAC1E,SAASA,EACN,OAAOA,EAAE,OAAO,GAAGA,EAAE,QAAQ,CAAC,CAAC,CAC/B,SAAS,CAAC,CACV,SACC,wFACF;AACJ,CAAC,GAIYC,IACX,uNAGWC,IAAaC,EAAgB;CACxC,MAAML;CACN,aAAaG;CACb,OAAOF;CACP,iBAAiB;AACnB,CAAC;AAMD,SAAgBK,EACd,GACA,IAA+BF,GACtB;CACT,IAAI,CAACG,EAAQ,QACX,MAAU,MAAM,yCAAyC;CAE3D,OAAOA,EAAQ,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC;EAAE;EAAW,OAAO,CAAC,MAAM;CAAE,CAAC,EAAE,EAAE,CAAC;AACjF;AAWA,eAAsBC,EAAY,GAAoB,GAAyC;CAC7F,IAAMC,IAAOC,EAAW,QAAQ,QAAQ,EAAE;CAiB1C,QAAO,MAhBa,QAAQ,IAC1BC,EAAO,IAAI,OAAO,MAAU;EAC1B,IAAI;GACF,IAAMC,IAAM,MAAM,MAAM,GAAGH,EAAK,sBAAsB,mBAAmBI,CAAK,GAAG;GACjF,IAAI,CAACD,EAAI,IACP,OAAO;GAET,IAAME,IAAK,MAAMF,EAAI,KAAK;GAC1B,OAAOE,EAAE,YACL;IAAE,OAAOA,EAAE;IAAO,OAAOA,EAAE;IAAO,aAAaA,EAAE;IAAa,QAAQA,EAAE,UAAU,CAAC;GAAE,IACrF;EACN,QAAQ;GACN,OAAO;EACT;CACF,CAAC,CACH,EAAA,CACa,QAAQ,MAAuBA,MAAM,IAAI;AACxD;AAEA,SAASC,EAAU,GAAwB;CACzC,IAAMC,IAAUC,EAAE,SAAS,SACvB,WAAWA,EAAE,QAAQ,KAAK,MAAM,KAAK,UAAUC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,MAC7D;CACJ,OAAO,GAAGD,EAAE,GAAG,IAAIA,EAAE,OAAOD,IAAUC,EAAE,WAAW,eAAe,GAAG,KAAKA,EAAE;AAC9E;AAGA,SAAgBE,EAAY,GAAiC;CAU3D,OATKC,EAAQ,SASN;EACL;EACA;EACA;EACA,uBAVWA,EACV,KACE,MACC,MAAMN,EAAE,MAAM,WAAWA,EAAE,MAAM,KAAKA,EAAE,YAAY,cAAcA,EAAE,OAAO,IAAIC,CAAS,CAAC,CAAC,KAAK,IAAI,KAAK,QAC5G,CAAC,CACA,KAAK,IAKiB;CACzB,IAbS,CAAC;AAcZ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@engenty/wizards",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "What your code imports from engenty wizards: plugins at /plugin, wizards in OpenUI chats at /openui.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "homepage": "https://engenty.ai",