getsyntux 0.1.1 → 0.1.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.
package/dist/index.js CHANGED
@@ -98,35 +98,36 @@ function extractChildren(element) {
98
98
  return [];
99
99
  }
100
100
  function searchChildren(element, acc) {
101
- const children = extractChildren(element);
102
- children.forEach((element2, index) => {
103
- if ((element2 == null ? void 0 : element2.type.identifier) === SIGNATURE) {
104
- const { values, components, hint } = element2.props;
105
- const realComponents = [];
106
- if (components) {
107
- components.forEach((comp) => {
108
- if (typeof comp === "string") {
109
- realComponents.push({
110
- llmName: comp
111
- });
112
- } else {
113
- realComponents.push({
114
- llmName: comp.llmName,
115
- llmContext: comp.llmContext,
116
- userContext: comp.userContext
117
- });
118
- }
119
- });
120
- }
121
- acc.push({
122
- values,
123
- components: realComponents,
124
- hint: hint || ""
101
+ if (!react.isValidElement(element)) return;
102
+ if (element.type.identifier === SIGNATURE) {
103
+ const { values, components, hint } = element.props;
104
+ const realComponents = [];
105
+ if (components) {
106
+ components.forEach((comp) => {
107
+ if (typeof comp === "string") {
108
+ realComponents.push({
109
+ llmName: comp
110
+ });
111
+ } else {
112
+ realComponents.push({
113
+ llmName: comp.llmName,
114
+ llmContext: comp.llmContext,
115
+ userContext: comp.userContext
116
+ });
117
+ }
125
118
  });
126
- } else {
127
- searchChildren(element2, acc);
128
119
  }
129
- });
120
+ acc.push({
121
+ values,
122
+ components: realComponents,
123
+ hint: hint || ""
124
+ });
125
+ } else {
126
+ const children = extractChildren(element);
127
+ children.forEach((child) => {
128
+ searchChildren(child, acc);
129
+ });
130
+ }
130
131
  }
131
132
  function generateInput(content, context) {
132
133
  let str = "";
@@ -176,13 +177,16 @@ function createComponentRegistry(components) {
176
177
  function hydrate(schema, dsl) {
177
178
  let componentIndex = 0;
178
179
  function swapChildren(element) {
180
+ if (!react.isValidElement(element)) return element;
181
+ if (element.type.identifier === SIGNATURE) {
182
+ const { values, components, hint } = element.props;
183
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { schema: dsl[componentIndex++], global: values, local: values, components: createComponentRegistry(components) }, componentIndex);
184
+ }
179
185
  const children = extractChildren(element);
186
+ if (children.length == 0) {
187
+ return element;
188
+ }
180
189
  return children.map((child, ind) => {
181
- if (!react.isValidElement(child)) return child;
182
- if (child.type.identifier === SIGNATURE) {
183
- const { values, components, hint } = child.props;
184
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { schema: dsl[componentIndex++], global: values, local: values, components: createComponentRegistry(components) }, ind);
185
- }
186
190
  return swapChildren(child);
187
191
  });
188
192
  }
@@ -200,6 +204,7 @@ var createGeneratedPage = (model) => {
200
204
  }
201
205
  const contents = [];
202
206
  searchChildren(schema, contents);
207
+ console.log("contents", contents);
203
208
  if (contents.length == 0) return schema;
204
209
  const llmInput = generateInput(contents, context);
205
210
  const { text: llmResponse } = await ai.generateText({
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/GeneratedContent.tsx","../src/Renderer.tsx","../src/util.ts","../src/prompt.md","../src/GeneratedPage.tsx","../src/index.ts"],"names":["jsx","Fragment","element","isValidElement","generateText"],"mappings":"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","file":"index.js","sourcesContent":["import { ComponentType } from 'react'\r\nimport { SyntuxComponent } from './types';\r\n\r\nexport interface GeneratedContentProps {\r\n values: any;\r\n components?: (SyntuxComponent<any> | string)[];\r\n hint?: string;\r\n}\r\n\r\n/**\r\n * Section of user interface for LLM to generate.\r\n * @param values The values (object, primitive, or array) to be displayed.\r\n * @param components List of allowed components that LLM can use.\r\n * @param hint Additional custom instructions for the LLM.\r\n */\r\nexport function GeneratedContent(props: GeneratedContentProps) {\r\n /**\r\n * This is an empty component.\r\n * It acts as a declarative slot that <GeneratedPage> recognizes\r\n * and replaces with a Renderer during hydration.\r\n */\r\n return <></>;\r\n}\r\nexport const SIGNATURE = Symbol('GeneratedContent');\r\nGeneratedContent.identifier = SIGNATURE;","import { ComponentType } from 'react'\r\n\r\nconst resolvePath = (obj: any, path: string) => {\r\n if(path === '$') return obj;\r\n return path.split('.').reduce((acc, curr) => acc?.[curr], obj)\r\n}\r\n\r\nconst get = (global: any, local: any, path: string) => {\r\n if(path.startsWith(\"$item.\")){\r\n path = path.slice(6)\r\n return resolvePath(local, path);\r\n } else {\r\n if(path === \"$item\") return local;\r\n return resolvePath(global, path);\r\n }\r\n}\r\n\r\nconst resolveProps = (global: any, local: any, props: any) => {\r\n if(!props) return;\r\n if(\"$bind\" in props) return get(global, local, props.$bind); // $bind may be falsy value\r\n Object.keys(props).forEach((key) => {\r\n const val = props[key];\r\n if(typeof val === \"object\"){\r\n props[key] = resolveProps(global, local, val);\r\n }\r\n })\r\n return props;\r\n}\r\n\r\nexport interface SchemaNode {\r\n type?: string;\r\n props?: Record<string, any>;\r\n children?: (SchemaNode | string)[];\r\n source?: string;\r\n template?: SchemaNode;\r\n $bind?: string;\r\n}\r\n\r\nexport interface RendererProps {\r\n schema: SchemaNode | string; // string occurs recursively\r\n global: any;\r\n local?: any;\r\n components: Record<string, ComponentType<any> | string>;\r\n}\r\n\r\nexport function Renderer({\r\n schema, global, local, components\r\n}: RendererProps) {\r\n if(typeof schema === \"string\") return <>{schema}</>;\r\n if(schema.$bind) {\r\n return <>{get(global, local, schema.$bind)}</>\r\n }\r\n\r\n if(schema.type === '__ForEach__' && schema.source && schema.template){\r\n const sourceArr = get(global, local, schema.source);\r\n if(!Array.isArray(sourceArr)) return null;\r\n\r\n return <>\r\n {sourceArr.map((item, index) => {\r\n return <Renderer\r\n key={index}\r\n schema={schema.template!}\r\n global={global}\r\n local={item}\r\n components={components}\r\n />\r\n })}\r\n </>\r\n }\r\n\r\n if(!schema.type) return null;\r\n\r\n const Component = components[schema.type] || schema.type;\r\n return <Component {...resolveProps(global, local, schema.props)}>\r\n {schema.children?.map((item, index) => {\r\n return <Renderer\r\n key={index}\r\n schema={item}\r\n global={global}\r\n local={local}\r\n components={components}\r\n />\r\n })}\r\n </Component>\r\n}\r\n","import { SchemaNode } from \"./Renderer\"\r\n\r\nconst endDelimiter = \"</UISchema>\"\r\nexport function parseResponse(llmResponse: string): SchemaNode[] {\r\n const split = llmResponse.split(/\\<UISchema index=\"\\d+\">/m).slice(1).map(e => e.trim())\r\n const contents = split.map(e => e.slice(0, -endDelimiter.length));\r\n const parsed = contents.map(e => JSON.parse(e))\r\n return parsed\r\n}","<system_persona>\r\nYou are the **UI Schema Generation Engine**, a specialized architect responsible for converting raw data structures into abstract, reusable React Interface Schemas (JSON-DSL).\r\n\r\nYour output is **NOT** code. Your output is a JSON-based Abstract Syntax Tree (AST) that describes the UI structure. The rendering engine will hydrate this schema with data later.\r\n</system_persona>\r\n\r\n<core_philosophy>\r\n1. **Separation of Concerns:** You define the *structure*. You do NOT hardcode *values*.\r\n2. **Strict Adherence:** You may ONLY use components explicitly listed in the `<AllowedComponents>` block of the input. If the block is missing or empty, revert to the <default_component_library>.\r\n3. **Semantic Structure:** Even though you are generating JSON, the resulting UI must be semantically correct (using proper hierarchy, semantic HTML tags, and logical grouping).\r\n4. **Reusability:** Your schema must be valid regardless of the specific values in the data. It must handle list lengths of 0 or 1000 gracefully using the Iterator Protocol.\r\n</core_philosophy>\r\n\r\n<dsl_syntax_rules>\r\nThe output must be a JSON object adhering to this strict recursive interface:\r\n\r\n### 1. The Standard Node\r\nUsed for HTML tags or Custom Components.\r\n```json\r\n{\r\n \"type\": \"div\" | \"h1\" | \"MyCustomComponent\",\r\n \"props\": { \"className\": \"...\", \"customProp\": \"...\" },\r\n \"children\": [] // Array of Nodes or Strings\r\n}\r\n```\r\n\r\n### 2. The Binding Protocol (`$bind`)\r\n\r\n**NEVER** output raw data values (e.g., \"John\", \"john@email.com\") in the schema.\r\nInstead, bind to a path.\r\n\r\n```json\r\n// BAD\r\n{ \"type\": \"span\", \"children\": [\"John\"] }\r\n\r\n// GOOD\r\n{ \"type\": \"span\", \"children\": [{ \"$bind\": \"user.firstName\" }] }\r\n```\r\n\r\nYou have access to exactly **two scopes** at any time:\r\n- **Global Scope (Root)**: Any path **WITHOUT** the `$item` prefix accesses the top-level global data object. This is available at any nesting depth.\r\n - *Example:* `\"$bind\": \"pageTitle\"` (Always looks at `data.pageTitle`)\r\n- **Local Scope (Current Item):** Any path **STARTING WITH** `$item` accesses the immediate object currently being iterated in a loop.\r\n - *Example:* `\"$bind\": \"$item.name\"` (Looks at `name` on the current loop item).\r\n - *Example:* `\"$bind\": \"$item\"` (Renders the current loop item, usually a string).\r\n\r\nIn special cases, you may need to reference a specific, fixed index in an array. To do that, use dot notation to access the index. For instance: `arr.1.property` accesses the `property` property of the 2nd item in `arr`. However, use this conservatively; prefer to use the Iterator Protocol unless it doesn't make sense (e.g., it's a static array).\r\n\r\n**CRITICAL:** Intermediate scopes are not accessible. Inside a nested loop, `$item` refers *only* to the innermost item.\r\n\r\n### 3. The Iterator Protocol (`__ForEach__`)\r\n\r\nIf the data value is an Array, you MUST use this node. Do not manually unroll lists.\r\n\r\n- **Root Arrays**: If the input value is the array itself, use \"source\": \"$\".\r\n- **Nested Arrays**: If the array is a property on the current item, use `\"source\": \"$item.path.to.array\"`.\r\n- **Global Arrays**: If the array is a property on the Global Root, use `\"source\": \"path.to.array\"`.\r\n\r\n```json\r\n{\r\n \"type\": \"__ForEach__\",\r\n \"source\": \"$\" | \"$item.path.to.array\" | \"path.to.array\",\r\n \"template\": {\r\n // This is the shape of a SINGLE item.\r\n // Inside here, use \"$item\" to refer to the current array element.\r\n \"type\": \"li\",\r\n \"children\": [{ \"$bind\": \"$item.name\" }]\r\n }\r\n}\r\n```\r\n\r\n</dsl_syntax_rules>\r\n\r\n<default_component_library>\r\nIf no specific allowed components are provided, you have access to this semantic HTML suite:\r\n\r\n * **Layout:** `div`, `section`, `article`, `main`, `aside`, `header`, `footer`\r\n * **Typography:** `h1`, `h2`, `h3`, `p`, `span`, `strong`, `em`, `blockquote`, `pre`, `code`\r\n * **Lists:** `ul`, `ol`, `li`\r\n * **Interaction:** `button`, `a` (use href prop), `details`, `summary`\r\n * **Form:** `input`, `label`, `textarea`, `select`, `option`\r\n * **Media:** `img`, `figure`, `figcaption`\r\n\r\n</default_component_library>\r\n\r\n<input_processing_rules>\r\nThe user will provide one or more `<GeneratedContent>` blocks.\r\n\r\n1. **Parse `AllowedComponents`:** A comma-separated list.\r\n * Lowercase = Native HTML tags.\r\n * Uppercase = Custom React Components.\r\n2. **Parse `ComponentContext`:** Defines the TypeScript interface for Custom Components.\r\n * *CRITICAL:* You must strictly adhere to the prop names and types defined here. Do not hallucinate props for custom components.\r\n * Components are separated by a comma, in the format `ComponentName [props: { ... }, details: \"...\"]`. The `props` indicate what `props` it must accept, in Typescript format. The `details` is an optional field, and describes what the component does. Use this information in whatever way to improve your generation output. If you encounter a complex type in `props`, look at the input values and make your best guess at what value is the best fit.\r\n3. **Parse `UserContext`:** This is anything the developer believes is relevant for your task. It could describe a specific UI style or the correct way to use a custom component.\r\n * *CRITICAL*: To the best of your ability, respect the developer's wishes. If no UserContext is provided, you should accomplish the task as you see fit, with no constraints.\r\n * *CRITICAL*: This is only relevant to the current <GeneratedContent> block!\r\n3. **Parse `Value`:** The JSON data structure you are building the UI for.\r\n\r\nAdditionally, the user may provide a <PageContext> before all <GeneratedContent> blocks. Think of this as a global UserContext. This is meant to provide additional context and guiding when designing the UI, which you should try to adhere to. If none is provided, accomplish the task as you see fit, with no constraints.\r\n\r\n</input_processing_rules>\r\n\r\n<output_formatting>\r\nFor every `<GeneratedContent>` input block, you must generate exactly one `<UISchema>` output block.\r\nThe order must be preserved.\r\n\r\nInput:\r\n<PageContext></PageContext>\r\n<GeneratedContent> ... </GeneratedContent> (Section 1)\r\n<GeneratedContent> ... </GeneratedContent> (Section 2)\r\n\r\nOutput:\r\n<UISchema index=\"0\"> ...JSON... </UISchema>\r\n<UISchema index=\"1\"> ...JSON... </UISchema>\r\n</output_formatting>\r\n\r\n<examples>\r\n**Input:**\r\n<GeneratedContent>\r\n<AllowedComponents>div,span,Avatar</AllowedComponents>\r\n<ComponentContext>Avatar [props: { url: string }]</ComponentContext>\r\n<UserContext>grouped under one div</UserContext>\r\n<Value>{ authors: [{ name: \"J.K.\", img: \"...\" }, { name: \"Tolkien\", img: \"...\" }] }</Value>\r\n</GeneratedContent>\r\n\r\n**Correct Output:**\r\n<UISchema index=\"0\">\r\n{\r\n \"type\": \"div\",\r\n \"props\": {\r\n \"className\": \"author-list\"\r\n },\r\n \"children\": [\r\n {\r\n \"type\": \"__ForEach__\",\r\n \"source\": \"authors\",\r\n \"template\": {\r\n \"type\": \"div\",\r\n \"props\": {\r\n \"className\": \"author-card\"\r\n },\r\n \"children\": [\r\n {\r\n \"type\": \"Avatar\",\r\n \"props\": {\r\n \"url\": {\r\n \"$bind\": \"$item.img\"\r\n }\r\n }\r\n },\r\n {\r\n \"type\": \"span\",\r\n \"children\": [\r\n {\r\n \"$bind\": \"$item.name\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n}\r\n</UISchema>\r\n</examples>\r\n\r\n<reasoning_requirements>\r\nBefore generating the JSON, briefly analyze the data structure to identify arrays (requiring `__ForEach__`) and custom component opportunities. Use the mental scratchpad if necessary, but keep the final output strictly within `<UISchema>` tags.\r\n</reasoning_requirements>\r\n\r\n<IMPORTANT>\r\nDo NOT output anything except the UISchema.\r\n</IMPORTANT>","import { isValidElement } from 'react';\r\nimport { GeneratedContentProps, SIGNATURE } from \"./GeneratedContent\";\r\nimport { Renderer, SchemaNode } from \"./Renderer\";\r\nimport { SyntuxComponent, SyntuxElement } from \"./types\";\r\nimport { parseResponse } from \"./util\";\r\nimport { generateText } from \"ai\";\r\nimport systemPrompt from './prompt.md';\r\n\r\nimport { type LanguageModel } from 'ai';\r\n\r\nexport interface GeneratedPageProps {\r\n context?: string;\r\n schema: SyntuxElement;\r\n onGenerate?: (result: SchemaNode[]) => void;\r\n cached?: (SchemaNode | string)[];\r\n}\r\n\r\nfunction extractChildren(element: any) {\r\n if (element?.props?.children) {\r\n let children = element.props.children;\r\n if (!Array.isArray(children)) children = [children];\r\n return children;\r\n }\r\n return [];\r\n}\r\n\r\nfunction searchChildren(element: any, acc: ContentSchema[]) {\r\n const children = extractChildren(element);\r\n\r\n children.forEach((element: SyntuxElement, index: number) => {\r\n if (element?.type.identifier === SIGNATURE) {\r\n const { values, components, hint } = element.props as GeneratedContentProps;\r\n const realComponents: any = []\r\n\r\n if (components) {\r\n components.forEach((comp: string | SyntuxComponent) => {\r\n if (typeof comp === \"string\") {\r\n realComponents.push({\r\n llmName: comp\r\n })\r\n } else {\r\n realComponents.push({\r\n llmName: comp.llmName,\r\n llmContext: comp.llmContext,\r\n userContext: comp.userContext\r\n })\r\n }\r\n })\r\n }\r\n acc.push({\r\n values, components: realComponents, hint: hint || \"\"\r\n })\r\n } else {\r\n searchChildren(element, acc)\r\n }\r\n })\r\n}\r\n\r\nfunction generateInput(content: ContentSchema[], context?: string) {\r\n let str = '';\r\n if (context) {\r\n str = `<PageContext>${context}</PageContext>\\n`;\r\n }\r\n\r\n content.forEach(schema => {\r\n const allowedComponents = schema.components.map(e => e.llmName);\r\n const componentContext: any = []\r\n schema.components.forEach(comp => {\r\n if (comp.llmContext) {\r\n let contextStr;\r\n if (comp.userContext) {\r\n contextStr = `${comp.llmName} [${comp.llmContext}, details: ${comp.userContext}]`\r\n } else {\r\n contextStr = `${comp.llmName} [${comp.llmContext}]`;\r\n }\r\n componentContext.push(contextStr)\r\n }\r\n })\r\n const userContext = schema.hint;\r\n const value = JSON.stringify(schema.values);\r\n\r\n str += `<GeneratedContent>\r\n <AllowedComponents>${allowedComponents.join(',')}</AllowedComponents>\r\n <ComponentContext>${componentContext.join(',')}</ComponentContext>\r\n <UserContext>${userContext}</UserContext>\r\n <Value>${value}</Value>\r\n</GeneratedContent>\\n`\r\n })\r\n\r\n return str;\r\n}\r\n\r\nfunction createComponentRegistry(components: (SyntuxComponent<any> | string)[] | undefined) {\r\n if (!components) return {};\r\n return components.reduce((acc: Record<string, SyntuxComponent<any> | string>, curr: SyntuxComponent<any> | string) => {\r\n if (typeof curr === \"string\") {\r\n acc[curr] = curr;\r\n } else {\r\n if (curr.llmName) {\r\n acc[curr.llmName] = curr;\r\n }\r\n }\r\n return acc;\r\n }, {})\r\n}\r\n\r\nfunction hydrate(schema: SyntuxElement, dsl: (SchemaNode | string)[]) {\r\n let componentIndex = 0;\r\n function swapChildren(element: SyntuxElement) {\r\n const children = extractChildren(element);\r\n\r\n return children.map((child: SyntuxElement, ind: number) => {\r\n if (!isValidElement(child)) return child;\r\n\r\n if (child.type.identifier === SIGNATURE) {\r\n const { values, components, hint } = child.props as GeneratedContentProps;\r\n return <Renderer key={ind} schema={dsl[componentIndex++]} global={values} local={values} components={createComponentRegistry(components)} />\r\n }\r\n\r\n return swapChildren(child);\r\n })\r\n }\r\n\r\n return swapChildren(schema);\r\n}\r\n\r\ninterface ContentSchema {\r\n values: any;\r\n components: { llmContext?: string, userContext?: string, llmName: string }[];\r\n hint: string;\r\n}\r\n\r\nexport const createGeneratedPage = (model: LanguageModel) => {\r\n /**\r\n * Container for content generation. Batches all <GeneratedContent> blocks into one LLM call.\r\n * \r\n * @param context Custom instructions for the LLM about the page, applicable to all components.\r\n * @param schema The structure of the page. Can be a mix of any type of component.\r\n * @param cached User provided React Interface Schema. Will skip schema generation if one is provided.\r\n * @param onGenerate Callback for receiving React Interface Schema after generation, to be used for caching. \r\n */\r\n return async function GeneratedPage({\r\n context, schema, cached, onGenerate\r\n }: GeneratedPageProps) {\r\n if(cached){\r\n return <>{hydrate(schema, cached)}</>\r\n }\r\n\r\n const contents: ContentSchema[] = [];\r\n searchChildren(schema, contents);\r\n\r\n if(contents.length == 0) return schema;\r\n\r\n const llmInput = generateInput(contents, context);\r\n\r\n const { text: llmResponse } = await generateText({\r\n model,\r\n system: systemPrompt,\r\n prompt: llmInput\r\n })\r\n const parsedResponse = parseResponse(llmResponse)\r\n\r\n if(onGenerate){\r\n onGenerate(parsedResponse)\r\n }\r\n \r\n return <>{hydrate(schema, parsedResponse)}</>\r\n }\r\n}","import { LanguageModel } from 'ai';\r\nimport { createGeneratedPage } from './GeneratedPage';\r\nimport { GeneratedContent } from './GeneratedContent';\r\nimport { Renderer } from './Renderer';\r\n\r\nexport { GeneratedContentProps } from './GeneratedContent';\r\nexport { GeneratedPageProps } from './GeneratedPage';\r\nexport {SchemaNode} from './Renderer';\r\n\r\nexport interface SyntuxFactoryConfig {\r\n model: LanguageModel;\r\n}\r\n\r\n\r\nexport const createSyntuxFactory = (config: SyntuxFactoryConfig) => {\r\n return {\r\n GeneratedPage: createGeneratedPage(config.model),\r\n GeneratedContent,\r\n Renderer\r\n }\r\n}"]}
1
+ {"version":3,"sources":["../src/GeneratedContent.tsx","../src/Renderer.tsx","../src/util.ts","../src/prompt.md","../src/GeneratedPage.tsx","../src/index.ts"],"names":["jsx","Fragment","isValidElement","generateText"],"mappings":"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","file":"index.js","sourcesContent":["import { ComponentType } from 'react'\r\nimport { SyntuxComponent } from './types';\r\n\r\nexport interface GeneratedContentProps {\r\n values: any;\r\n components?: (SyntuxComponent<any> | string)[];\r\n hint?: string;\r\n}\r\n\r\n/**\r\n * Section of user interface for LLM to generate.\r\n * @param values The values (object, primitive, or array) to be displayed.\r\n * @param components List of allowed components that LLM can use.\r\n * @param hint Additional custom instructions for the LLM.\r\n */\r\nexport function GeneratedContent(props: GeneratedContentProps) {\r\n /**\r\n * This is an empty component.\r\n * It acts as a declarative slot that <GeneratedPage> recognizes\r\n * and replaces with a Renderer during hydration.\r\n */\r\n return <></>;\r\n}\r\nexport const SIGNATURE = Symbol('GeneratedContent');\r\nGeneratedContent.identifier = SIGNATURE;","import { ComponentType } from 'react'\r\n\r\nconst resolvePath = (obj: any, path: string) => {\r\n if(path === '$') return obj;\r\n return path.split('.').reduce((acc, curr) => acc?.[curr], obj)\r\n}\r\n\r\nconst get = (global: any, local: any, path: string) => {\r\n if(path.startsWith(\"$item.\")){\r\n path = path.slice(6)\r\n return resolvePath(local, path);\r\n } else {\r\n if(path === \"$item\") return local;\r\n return resolvePath(global, path);\r\n }\r\n}\r\n\r\nconst resolveProps = (global: any, local: any, props: any) => {\r\n if(!props) return;\r\n if(\"$bind\" in props) return get(global, local, props.$bind); // $bind may be falsy value\r\n Object.keys(props).forEach((key) => {\r\n const val = props[key];\r\n if(typeof val === \"object\"){\r\n props[key] = resolveProps(global, local, val);\r\n }\r\n })\r\n return props;\r\n}\r\n\r\nexport interface SchemaNode {\r\n type?: string;\r\n props?: Record<string, any>;\r\n children?: (SchemaNode | string)[];\r\n source?: string;\r\n template?: SchemaNode;\r\n $bind?: string;\r\n}\r\n\r\nexport interface RendererProps {\r\n schema: SchemaNode | string; // string occurs recursively\r\n global: any;\r\n local?: any;\r\n components: Record<string, ComponentType<any> | string>;\r\n}\r\n\r\nexport function Renderer({\r\n schema, global, local, components\r\n}: RendererProps) {\r\n if(typeof schema === \"string\") return <>{schema}</>;\r\n if(schema.$bind) {\r\n return <>{get(global, local, schema.$bind)}</>\r\n }\r\n\r\n if(schema.type === '__ForEach__' && schema.source && schema.template){\r\n const sourceArr = get(global, local, schema.source);\r\n if(!Array.isArray(sourceArr)) return null;\r\n\r\n return <>\r\n {sourceArr.map((item, index) => {\r\n return <Renderer\r\n key={index}\r\n schema={schema.template!}\r\n global={global}\r\n local={item}\r\n components={components}\r\n />\r\n })}\r\n </>\r\n }\r\n\r\n if(!schema.type) return null;\r\n\r\n const Component = components[schema.type] || schema.type;\r\n return <Component {...resolveProps(global, local, schema.props)}>\r\n {schema.children?.map((item, index) => {\r\n return <Renderer\r\n key={index}\r\n schema={item}\r\n global={global}\r\n local={local}\r\n components={components}\r\n />\r\n })}\r\n </Component>\r\n}\r\n","import { SchemaNode } from \"./Renderer\"\r\n\r\nconst endDelimiter = \"</UISchema>\"\r\nexport function parseResponse(llmResponse: string): SchemaNode[] {\r\n const split = llmResponse.split(/\\<UISchema index=\"\\d+\">/m).slice(1).map(e => e.trim())\r\n const contents = split.map(e => e.slice(0, -endDelimiter.length));\r\n const parsed = contents.map(e => JSON.parse(e))\r\n return parsed\r\n}","<system_persona>\r\nYou are the **UI Schema Generation Engine**, a specialized architect responsible for converting raw data structures into abstract, reusable React Interface Schemas (JSON-DSL).\r\n\r\nYour output is **NOT** code. Your output is a JSON-based Abstract Syntax Tree (AST) that describes the UI structure. The rendering engine will hydrate this schema with data later.\r\n</system_persona>\r\n\r\n<core_philosophy>\r\n1. **Separation of Concerns:** You define the *structure*. You do NOT hardcode *values*.\r\n2. **Strict Adherence:** You may ONLY use components explicitly listed in the `<AllowedComponents>` block of the input. If the block is missing or empty, revert to the <default_component_library>.\r\n3. **Semantic Structure:** Even though you are generating JSON, the resulting UI must be semantically correct (using proper hierarchy, semantic HTML tags, and logical grouping).\r\n4. **Reusability:** Your schema must be valid regardless of the specific values in the data. It must handle list lengths of 0 or 1000 gracefully using the Iterator Protocol.\r\n</core_philosophy>\r\n\r\n<dsl_syntax_rules>\r\nThe output must be a JSON object adhering to this strict recursive interface:\r\n\r\n### 1. The Standard Node\r\nUsed for HTML tags or Custom Components.\r\n```json\r\n{\r\n \"type\": \"div\" | \"h1\" | \"MyCustomComponent\",\r\n \"props\": { \"className\": \"...\", \"customProp\": \"...\" },\r\n \"children\": [] // Array of Nodes or Strings\r\n}\r\n```\r\n\r\n### 2. The Binding Protocol (`$bind`)\r\n\r\n**NEVER** output raw data values (e.g., \"John\", \"john@email.com\") in the schema.\r\nInstead, bind to a path.\r\n\r\n```json\r\n// BAD\r\n{ \"type\": \"span\", \"children\": [\"John\"] }\r\n\r\n// GOOD\r\n{ \"type\": \"span\", \"children\": [{ \"$bind\": \"user.firstName\" }] }\r\n```\r\n\r\nYou have access to exactly **two scopes** at any time:\r\n- **Global Scope (Root)**: Any path **WITHOUT** the `$item` prefix accesses the top-level global data object. This is available at any nesting depth.\r\n - *Example:* `\"$bind\": \"pageTitle\"` (Always looks at `data.pageTitle`)\r\n- **Local Scope (Current Item):** Any path **STARTING WITH** `$item` accesses the immediate object currently being iterated in a loop.\r\n - *Example:* `\"$bind\": \"$item.name\"` (Looks at `name` on the current loop item).\r\n - *Example:* `\"$bind\": \"$item\"` (Renders the current loop item, usually a string).\r\n\r\nIn special cases, you may need to reference a specific, fixed index in an array. To do that, use dot notation to access the index. For instance: `arr.1.property` accesses the `property` property of the 2nd item in `arr`. However, use this conservatively; prefer to use the Iterator Protocol unless it doesn't make sense (e.g., it's a static array).\r\n\r\n**CRITICAL:** Intermediate scopes are not accessible. Inside a nested loop, `$item` refers *only* to the innermost item.\r\n\r\n### 3. The Iterator Protocol (`__ForEach__`)\r\n\r\nIf the data value is an Array, you MUST use this node. Do not manually unroll lists.\r\n\r\n- **Root Arrays**: If the input value is the array itself, use \"source\": \"$\".\r\n- **Nested Arrays**: If the array is a property on the current item, use `\"source\": \"$item.path.to.array\"`.\r\n- **Global Arrays**: If the array is a property on the Global Root, use `\"source\": \"path.to.array\"`.\r\n\r\n```json\r\n{\r\n \"type\": \"__ForEach__\",\r\n \"source\": \"$\" | \"$item.path.to.array\" | \"path.to.array\",\r\n \"template\": {\r\n // This is the shape of a SINGLE item.\r\n // Inside here, use \"$item\" to refer to the current array element.\r\n \"type\": \"li\",\r\n \"children\": [{ \"$bind\": \"$item.name\" }]\r\n }\r\n}\r\n```\r\n\r\n</dsl_syntax_rules>\r\n\r\n<default_component_library>\r\nIf no specific allowed components are provided, you have access to this semantic HTML suite:\r\n\r\n * **Layout:** `div`, `section`, `article`, `main`, `aside`, `header`, `footer`\r\n * **Typography:** `h1`, `h2`, `h3`, `p`, `span`, `strong`, `em`, `blockquote`, `pre`, `code`\r\n * **Lists:** `ul`, `ol`, `li`\r\n * **Interaction:** `button`, `a` (use href prop), `details`, `summary`\r\n * **Form:** `input`, `label`, `textarea`, `select`, `option`\r\n * **Media:** `img`, `figure`, `figcaption`\r\n\r\n</default_component_library>\r\n\r\n<input_processing_rules>\r\nThe user will provide one or more `<GeneratedContent>` blocks.\r\n\r\n1. **Parse `AllowedComponents`:** A comma-separated list.\r\n * Lowercase = Native HTML tags.\r\n * Uppercase = Custom React Components.\r\n2. **Parse `ComponentContext`:** Defines the TypeScript interface for Custom Components.\r\n * *CRITICAL:* You must strictly adhere to the prop names and types defined here. Do not hallucinate props for custom components.\r\n * Components are separated by a comma, in the format `ComponentName [props: { ... }, details: \"...\"]`. The `props` indicate what `props` it must accept, in Typescript format. The `details` is an optional field, and describes what the component does. Use this information in whatever way to improve your generation output. If you encounter a complex type in `props`, look at the input values and make your best guess at what value is the best fit.\r\n3. **Parse `UserContext`:** This is anything the developer believes is relevant for your task. It could describe a specific UI style or the correct way to use a custom component.\r\n * *CRITICAL*: To the best of your ability, respect the developer's wishes. If no UserContext is provided, you should accomplish the task as you see fit, with no constraints.\r\n * *CRITICAL*: This is only relevant to the current <GeneratedContent> block!\r\n3. **Parse `Value`:** The JSON data structure you are building the UI for.\r\n\r\nAdditionally, the user may provide a <PageContext> before all <GeneratedContent> blocks. Think of this as a global UserContext. This is meant to provide additional context and guiding when designing the UI, which you should try to adhere to. If none is provided, accomplish the task as you see fit, with no constraints.\r\n\r\n</input_processing_rules>\r\n\r\n<output_formatting>\r\nFor every `<GeneratedContent>` input block, you must generate exactly one `<UISchema>` output block.\r\nThe order must be preserved.\r\n\r\nInput:\r\n<PageContext></PageContext>\r\n<GeneratedContent> ... </GeneratedContent> (Section 1)\r\n<GeneratedContent> ... </GeneratedContent> (Section 2)\r\n\r\nOutput:\r\n<UISchema index=\"0\"> ...JSON... </UISchema>\r\n<UISchema index=\"1\"> ...JSON... </UISchema>\r\n</output_formatting>\r\n\r\n<examples>\r\n**Input:**\r\n<GeneratedContent>\r\n<AllowedComponents>div,span,Avatar</AllowedComponents>\r\n<ComponentContext>Avatar [props: { url: string }]</ComponentContext>\r\n<UserContext>grouped under one div</UserContext>\r\n<Value>{ authors: [{ name: \"J.K.\", img: \"...\" }, { name: \"Tolkien\", img: \"...\" }] }</Value>\r\n</GeneratedContent>\r\n\r\n**Correct Output:**\r\n<UISchema index=\"0\">\r\n{\r\n \"type\": \"div\",\r\n \"props\": {\r\n \"className\": \"author-list\"\r\n },\r\n \"children\": [\r\n {\r\n \"type\": \"__ForEach__\",\r\n \"source\": \"authors\",\r\n \"template\": {\r\n \"type\": \"div\",\r\n \"props\": {\r\n \"className\": \"author-card\"\r\n },\r\n \"children\": [\r\n {\r\n \"type\": \"Avatar\",\r\n \"props\": {\r\n \"url\": {\r\n \"$bind\": \"$item.img\"\r\n }\r\n }\r\n },\r\n {\r\n \"type\": \"span\",\r\n \"children\": [\r\n {\r\n \"$bind\": \"$item.name\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n}\r\n</UISchema>\r\n</examples>\r\n\r\n<reasoning_requirements>\r\nBefore generating the JSON, briefly analyze the data structure to identify arrays (requiring `__ForEach__`) and custom component opportunities. Use the mental scratchpad if necessary, but keep the final output strictly within `<UISchema>` tags.\r\n</reasoning_requirements>\r\n\r\n<IMPORTANT>\r\nDo NOT output anything except the UISchema.\r\n</IMPORTANT>","import { isValidElement } from 'react';\r\nimport { GeneratedContentProps, SIGNATURE } from \"./GeneratedContent\";\r\nimport { Renderer, SchemaNode } from \"./Renderer\";\r\nimport { SyntuxComponent, SyntuxElement } from \"./types\";\r\nimport { parseResponse } from \"./util\";\r\nimport { generateText } from \"ai\";\r\nimport systemPrompt from './prompt.md';\r\n\r\nimport { type LanguageModel } from 'ai';\r\n\r\nexport interface GeneratedPageProps {\r\n context?: string;\r\n schema: SyntuxElement;\r\n onGenerate?: (result: SchemaNode[]) => void;\r\n cached?: (SchemaNode | string)[];\r\n}\r\n\r\nfunction extractChildren(element: any) {\r\n if (element?.props?.children) {\r\n let children = element.props.children;\r\n if (!Array.isArray(children)) children = [children];\r\n return children;\r\n }\r\n return [];\r\n}\r\n\r\nfunction searchChildren(element: SyntuxElement, acc: ContentSchema[]) {\r\n if(!isValidElement(element)) return;\r\n\r\n if(element.type.identifier === SIGNATURE){\r\n const { values, components, hint } = element.props as GeneratedContentProps;\r\n const realComponents: any = []\r\n\r\n if (components) {\r\n components.forEach((comp: string | SyntuxComponent) => {\r\n if (typeof comp === \"string\") {\r\n realComponents.push({\r\n llmName: comp\r\n })\r\n } else {\r\n realComponents.push({\r\n llmName: comp.llmName,\r\n llmContext: comp.llmContext,\r\n userContext: comp.userContext\r\n })\r\n }\r\n })\r\n }\r\n acc.push({\r\n values, components: realComponents, hint: hint || \"\"\r\n })\r\n } else {\r\n const children = extractChildren(element);\r\n children.forEach((child: SyntuxElement) => {\r\n searchChildren(child, acc)\r\n })\r\n }\r\n}\r\n\r\nfunction generateInput(content: ContentSchema[], context?: string) {\r\n let str = '';\r\n if (context) {\r\n str = `<PageContext>${context}</PageContext>\\n`;\r\n }\r\n\r\n content.forEach(schema => {\r\n const allowedComponents = schema.components.map(e => e.llmName);\r\n const componentContext: any = []\r\n schema.components.forEach(comp => {\r\n if (comp.llmContext) {\r\n let contextStr;\r\n if (comp.userContext) {\r\n contextStr = `${comp.llmName} [${comp.llmContext}, details: ${comp.userContext}]`\r\n } else {\r\n contextStr = `${comp.llmName} [${comp.llmContext}]`;\r\n }\r\n componentContext.push(contextStr)\r\n }\r\n })\r\n const userContext = schema.hint;\r\n const value = JSON.stringify(schema.values);\r\n\r\n str += `<GeneratedContent>\r\n <AllowedComponents>${allowedComponents.join(',')}</AllowedComponents>\r\n <ComponentContext>${componentContext.join(',')}</ComponentContext>\r\n <UserContext>${userContext}</UserContext>\r\n <Value>${value}</Value>\r\n</GeneratedContent>\\n`\r\n })\r\n\r\n return str;\r\n}\r\n\r\nfunction createComponentRegistry(components: (SyntuxComponent<any> | string)[] | undefined) {\r\n if (!components) return {};\r\n return components.reduce((acc: Record<string, SyntuxComponent<any> | string>, curr: SyntuxComponent<any> | string) => {\r\n if (typeof curr === \"string\") {\r\n acc[curr] = curr;\r\n } else {\r\n if (curr.llmName) {\r\n acc[curr.llmName] = curr;\r\n }\r\n }\r\n return acc;\r\n }, {})\r\n}\r\n\r\nfunction hydrate(schema: SyntuxElement, dsl: (SchemaNode | string)[]) {\r\n let componentIndex = 0;\r\n function swapChildren(element: SyntuxElement) {\r\n if(!isValidElement(element)) return element;\r\n\r\n if(element.type.identifier === SIGNATURE){\r\n const { values, components, hint } = element.props as GeneratedContentProps;\r\n return <Renderer key={componentIndex} schema={dsl[componentIndex++]} global={values} local={values} components={createComponentRegistry(components)} />;\r\n }\r\n\r\n\r\n const children = extractChildren(element);\r\n\r\n if(children.length == 0){\r\n return element;\r\n }\r\n\r\n return children.map((child: SyntuxElement, ind: number) => {\r\n return swapChildren(child);\r\n })\r\n }\r\n\r\n return swapChildren(schema);\r\n}\r\n\r\ninterface ContentSchema {\r\n values: any;\r\n components: { llmContext?: string, userContext?: string, llmName: string }[];\r\n hint: string;\r\n}\r\n\r\nexport const createGeneratedPage = (model: LanguageModel) => {\r\n /**\r\n * Container for content generation. Batches all <GeneratedContent> blocks into one LLM call.\r\n * \r\n * @param context Custom instructions for the LLM about the page, applicable to all components.\r\n * @param schema The structure of the page. Can be a mix of any type of component.\r\n * @param cached User provided React Interface Schema. Will skip schema generation if one is provided.\r\n * @param onGenerate Callback for receiving React Interface Schema after generation, to be used for caching. \r\n */\r\n return async function GeneratedPage({\r\n context, schema, cached, onGenerate\r\n }: GeneratedPageProps) {\r\n if(cached){\r\n return <>{hydrate(schema, cached)}</>\r\n }\r\n\r\n const contents: ContentSchema[] = [];\r\n searchChildren(schema, contents);\r\n console.log('contents', contents);\r\n \r\n if(contents.length == 0) return schema;\r\n\r\n const llmInput = generateInput(contents, context);\r\n\r\n const { text: llmResponse } = await generateText({\r\n model,\r\n system: systemPrompt,\r\n prompt: llmInput\r\n })\r\n const parsedResponse = parseResponse(llmResponse)\r\n\r\n if(onGenerate){\r\n onGenerate(parsedResponse)\r\n }\r\n \r\n return <>{hydrate(schema, parsedResponse)}</>\r\n }\r\n}","import { LanguageModel } from 'ai';\r\nimport { createGeneratedPage } from './GeneratedPage';\r\nimport { GeneratedContent } from './GeneratedContent';\r\nimport { Renderer } from './Renderer';\r\n\r\nexport { GeneratedContentProps } from './GeneratedContent';\r\nexport { GeneratedPageProps } from './GeneratedPage';\r\nexport {SchemaNode} from './Renderer';\r\n\r\nexport interface SyntuxFactoryConfig {\r\n model: LanguageModel;\r\n}\r\n\r\n\r\nexport const createSyntuxFactory = (config: SyntuxFactoryConfig) => {\r\n return {\r\n GeneratedPage: createGeneratedPage(config.model),\r\n GeneratedContent,\r\n Renderer\r\n }\r\n}"]}
package/dist/index.mjs CHANGED
@@ -96,35 +96,36 @@ function extractChildren(element) {
96
96
  return [];
97
97
  }
98
98
  function searchChildren(element, acc) {
99
- const children = extractChildren(element);
100
- children.forEach((element2, index) => {
101
- if ((element2 == null ? void 0 : element2.type.identifier) === SIGNATURE) {
102
- const { values, components, hint } = element2.props;
103
- const realComponents = [];
104
- if (components) {
105
- components.forEach((comp) => {
106
- if (typeof comp === "string") {
107
- realComponents.push({
108
- llmName: comp
109
- });
110
- } else {
111
- realComponents.push({
112
- llmName: comp.llmName,
113
- llmContext: comp.llmContext,
114
- userContext: comp.userContext
115
- });
116
- }
117
- });
118
- }
119
- acc.push({
120
- values,
121
- components: realComponents,
122
- hint: hint || ""
99
+ if (!isValidElement(element)) return;
100
+ if (element.type.identifier === SIGNATURE) {
101
+ const { values, components, hint } = element.props;
102
+ const realComponents = [];
103
+ if (components) {
104
+ components.forEach((comp) => {
105
+ if (typeof comp === "string") {
106
+ realComponents.push({
107
+ llmName: comp
108
+ });
109
+ } else {
110
+ realComponents.push({
111
+ llmName: comp.llmName,
112
+ llmContext: comp.llmContext,
113
+ userContext: comp.userContext
114
+ });
115
+ }
123
116
  });
124
- } else {
125
- searchChildren(element2, acc);
126
117
  }
127
- });
118
+ acc.push({
119
+ values,
120
+ components: realComponents,
121
+ hint: hint || ""
122
+ });
123
+ } else {
124
+ const children = extractChildren(element);
125
+ children.forEach((child) => {
126
+ searchChildren(child, acc);
127
+ });
128
+ }
128
129
  }
129
130
  function generateInput(content, context) {
130
131
  let str = "";
@@ -174,13 +175,16 @@ function createComponentRegistry(components) {
174
175
  function hydrate(schema, dsl) {
175
176
  let componentIndex = 0;
176
177
  function swapChildren(element) {
178
+ if (!isValidElement(element)) return element;
179
+ if (element.type.identifier === SIGNATURE) {
180
+ const { values, components, hint } = element.props;
181
+ return /* @__PURE__ */ jsx(Renderer, { schema: dsl[componentIndex++], global: values, local: values, components: createComponentRegistry(components) }, componentIndex);
182
+ }
177
183
  const children = extractChildren(element);
184
+ if (children.length == 0) {
185
+ return element;
186
+ }
178
187
  return children.map((child, ind) => {
179
- if (!isValidElement(child)) return child;
180
- if (child.type.identifier === SIGNATURE) {
181
- const { values, components, hint } = child.props;
182
- return /* @__PURE__ */ jsx(Renderer, { schema: dsl[componentIndex++], global: values, local: values, components: createComponentRegistry(components) }, ind);
183
- }
184
188
  return swapChildren(child);
185
189
  });
186
190
  }
@@ -198,6 +202,7 @@ var createGeneratedPage = (model) => {
198
202
  }
199
203
  const contents = [];
200
204
  searchChildren(schema, contents);
205
+ console.log("contents", contents);
201
206
  if (contents.length == 0) return schema;
202
207
  const llmInput = generateInput(contents, context);
203
208
  const { text: llmResponse } = await generateText({
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/GeneratedContent.tsx","../src/Renderer.tsx","../src/util.ts","../src/prompt.md","../src/GeneratedPage.tsx","../src/index.ts"],"names":["jsx","Fragment","element"],"mappings":"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","file":"index.mjs","sourcesContent":["import { ComponentType } from 'react'\r\nimport { SyntuxComponent } from './types';\r\n\r\nexport interface GeneratedContentProps {\r\n values: any;\r\n components?: (SyntuxComponent<any> | string)[];\r\n hint?: string;\r\n}\r\n\r\n/**\r\n * Section of user interface for LLM to generate.\r\n * @param values The values (object, primitive, or array) to be displayed.\r\n * @param components List of allowed components that LLM can use.\r\n * @param hint Additional custom instructions for the LLM.\r\n */\r\nexport function GeneratedContent(props: GeneratedContentProps) {\r\n /**\r\n * This is an empty component.\r\n * It acts as a declarative slot that <GeneratedPage> recognizes\r\n * and replaces with a Renderer during hydration.\r\n */\r\n return <></>;\r\n}\r\nexport const SIGNATURE = Symbol('GeneratedContent');\r\nGeneratedContent.identifier = SIGNATURE;","import { ComponentType } from 'react'\r\n\r\nconst resolvePath = (obj: any, path: string) => {\r\n if(path === '$') return obj;\r\n return path.split('.').reduce((acc, curr) => acc?.[curr], obj)\r\n}\r\n\r\nconst get = (global: any, local: any, path: string) => {\r\n if(path.startsWith(\"$item.\")){\r\n path = path.slice(6)\r\n return resolvePath(local, path);\r\n } else {\r\n if(path === \"$item\") return local;\r\n return resolvePath(global, path);\r\n }\r\n}\r\n\r\nconst resolveProps = (global: any, local: any, props: any) => {\r\n if(!props) return;\r\n if(\"$bind\" in props) return get(global, local, props.$bind); // $bind may be falsy value\r\n Object.keys(props).forEach((key) => {\r\n const val = props[key];\r\n if(typeof val === \"object\"){\r\n props[key] = resolveProps(global, local, val);\r\n }\r\n })\r\n return props;\r\n}\r\n\r\nexport interface SchemaNode {\r\n type?: string;\r\n props?: Record<string, any>;\r\n children?: (SchemaNode | string)[];\r\n source?: string;\r\n template?: SchemaNode;\r\n $bind?: string;\r\n}\r\n\r\nexport interface RendererProps {\r\n schema: SchemaNode | string; // string occurs recursively\r\n global: any;\r\n local?: any;\r\n components: Record<string, ComponentType<any> | string>;\r\n}\r\n\r\nexport function Renderer({\r\n schema, global, local, components\r\n}: RendererProps) {\r\n if(typeof schema === \"string\") return <>{schema}</>;\r\n if(schema.$bind) {\r\n return <>{get(global, local, schema.$bind)}</>\r\n }\r\n\r\n if(schema.type === '__ForEach__' && schema.source && schema.template){\r\n const sourceArr = get(global, local, schema.source);\r\n if(!Array.isArray(sourceArr)) return null;\r\n\r\n return <>\r\n {sourceArr.map((item, index) => {\r\n return <Renderer\r\n key={index}\r\n schema={schema.template!}\r\n global={global}\r\n local={item}\r\n components={components}\r\n />\r\n })}\r\n </>\r\n }\r\n\r\n if(!schema.type) return null;\r\n\r\n const Component = components[schema.type] || schema.type;\r\n return <Component {...resolveProps(global, local, schema.props)}>\r\n {schema.children?.map((item, index) => {\r\n return <Renderer\r\n key={index}\r\n schema={item}\r\n global={global}\r\n local={local}\r\n components={components}\r\n />\r\n })}\r\n </Component>\r\n}\r\n","import { SchemaNode } from \"./Renderer\"\r\n\r\nconst endDelimiter = \"</UISchema>\"\r\nexport function parseResponse(llmResponse: string): SchemaNode[] {\r\n const split = llmResponse.split(/\\<UISchema index=\"\\d+\">/m).slice(1).map(e => e.trim())\r\n const contents = split.map(e => e.slice(0, -endDelimiter.length));\r\n const parsed = contents.map(e => JSON.parse(e))\r\n return parsed\r\n}","<system_persona>\r\nYou are the **UI Schema Generation Engine**, a specialized architect responsible for converting raw data structures into abstract, reusable React Interface Schemas (JSON-DSL).\r\n\r\nYour output is **NOT** code. Your output is a JSON-based Abstract Syntax Tree (AST) that describes the UI structure. The rendering engine will hydrate this schema with data later.\r\n</system_persona>\r\n\r\n<core_philosophy>\r\n1. **Separation of Concerns:** You define the *structure*. You do NOT hardcode *values*.\r\n2. **Strict Adherence:** You may ONLY use components explicitly listed in the `<AllowedComponents>` block of the input. If the block is missing or empty, revert to the <default_component_library>.\r\n3. **Semantic Structure:** Even though you are generating JSON, the resulting UI must be semantically correct (using proper hierarchy, semantic HTML tags, and logical grouping).\r\n4. **Reusability:** Your schema must be valid regardless of the specific values in the data. It must handle list lengths of 0 or 1000 gracefully using the Iterator Protocol.\r\n</core_philosophy>\r\n\r\n<dsl_syntax_rules>\r\nThe output must be a JSON object adhering to this strict recursive interface:\r\n\r\n### 1. The Standard Node\r\nUsed for HTML tags or Custom Components.\r\n```json\r\n{\r\n \"type\": \"div\" | \"h1\" | \"MyCustomComponent\",\r\n \"props\": { \"className\": \"...\", \"customProp\": \"...\" },\r\n \"children\": [] // Array of Nodes or Strings\r\n}\r\n```\r\n\r\n### 2. The Binding Protocol (`$bind`)\r\n\r\n**NEVER** output raw data values (e.g., \"John\", \"john@email.com\") in the schema.\r\nInstead, bind to a path.\r\n\r\n```json\r\n// BAD\r\n{ \"type\": \"span\", \"children\": [\"John\"] }\r\n\r\n// GOOD\r\n{ \"type\": \"span\", \"children\": [{ \"$bind\": \"user.firstName\" }] }\r\n```\r\n\r\nYou have access to exactly **two scopes** at any time:\r\n- **Global Scope (Root)**: Any path **WITHOUT** the `$item` prefix accesses the top-level global data object. This is available at any nesting depth.\r\n - *Example:* `\"$bind\": \"pageTitle\"` (Always looks at `data.pageTitle`)\r\n- **Local Scope (Current Item):** Any path **STARTING WITH** `$item` accesses the immediate object currently being iterated in a loop.\r\n - *Example:* `\"$bind\": \"$item.name\"` (Looks at `name` on the current loop item).\r\n - *Example:* `\"$bind\": \"$item\"` (Renders the current loop item, usually a string).\r\n\r\nIn special cases, you may need to reference a specific, fixed index in an array. To do that, use dot notation to access the index. For instance: `arr.1.property` accesses the `property` property of the 2nd item in `arr`. However, use this conservatively; prefer to use the Iterator Protocol unless it doesn't make sense (e.g., it's a static array).\r\n\r\n**CRITICAL:** Intermediate scopes are not accessible. Inside a nested loop, `$item` refers *only* to the innermost item.\r\n\r\n### 3. The Iterator Protocol (`__ForEach__`)\r\n\r\nIf the data value is an Array, you MUST use this node. Do not manually unroll lists.\r\n\r\n- **Root Arrays**: If the input value is the array itself, use \"source\": \"$\".\r\n- **Nested Arrays**: If the array is a property on the current item, use `\"source\": \"$item.path.to.array\"`.\r\n- **Global Arrays**: If the array is a property on the Global Root, use `\"source\": \"path.to.array\"`.\r\n\r\n```json\r\n{\r\n \"type\": \"__ForEach__\",\r\n \"source\": \"$\" | \"$item.path.to.array\" | \"path.to.array\",\r\n \"template\": {\r\n // This is the shape of a SINGLE item.\r\n // Inside here, use \"$item\" to refer to the current array element.\r\n \"type\": \"li\",\r\n \"children\": [{ \"$bind\": \"$item.name\" }]\r\n }\r\n}\r\n```\r\n\r\n</dsl_syntax_rules>\r\n\r\n<default_component_library>\r\nIf no specific allowed components are provided, you have access to this semantic HTML suite:\r\n\r\n * **Layout:** `div`, `section`, `article`, `main`, `aside`, `header`, `footer`\r\n * **Typography:** `h1`, `h2`, `h3`, `p`, `span`, `strong`, `em`, `blockquote`, `pre`, `code`\r\n * **Lists:** `ul`, `ol`, `li`\r\n * **Interaction:** `button`, `a` (use href prop), `details`, `summary`\r\n * **Form:** `input`, `label`, `textarea`, `select`, `option`\r\n * **Media:** `img`, `figure`, `figcaption`\r\n\r\n</default_component_library>\r\n\r\n<input_processing_rules>\r\nThe user will provide one or more `<GeneratedContent>` blocks.\r\n\r\n1. **Parse `AllowedComponents`:** A comma-separated list.\r\n * Lowercase = Native HTML tags.\r\n * Uppercase = Custom React Components.\r\n2. **Parse `ComponentContext`:** Defines the TypeScript interface for Custom Components.\r\n * *CRITICAL:* You must strictly adhere to the prop names and types defined here. Do not hallucinate props for custom components.\r\n * Components are separated by a comma, in the format `ComponentName [props: { ... }, details: \"...\"]`. The `props` indicate what `props` it must accept, in Typescript format. The `details` is an optional field, and describes what the component does. Use this information in whatever way to improve your generation output. If you encounter a complex type in `props`, look at the input values and make your best guess at what value is the best fit.\r\n3. **Parse `UserContext`:** This is anything the developer believes is relevant for your task. It could describe a specific UI style or the correct way to use a custom component.\r\n * *CRITICAL*: To the best of your ability, respect the developer's wishes. If no UserContext is provided, you should accomplish the task as you see fit, with no constraints.\r\n * *CRITICAL*: This is only relevant to the current <GeneratedContent> block!\r\n3. **Parse `Value`:** The JSON data structure you are building the UI for.\r\n\r\nAdditionally, the user may provide a <PageContext> before all <GeneratedContent> blocks. Think of this as a global UserContext. This is meant to provide additional context and guiding when designing the UI, which you should try to adhere to. If none is provided, accomplish the task as you see fit, with no constraints.\r\n\r\n</input_processing_rules>\r\n\r\n<output_formatting>\r\nFor every `<GeneratedContent>` input block, you must generate exactly one `<UISchema>` output block.\r\nThe order must be preserved.\r\n\r\nInput:\r\n<PageContext></PageContext>\r\n<GeneratedContent> ... </GeneratedContent> (Section 1)\r\n<GeneratedContent> ... </GeneratedContent> (Section 2)\r\n\r\nOutput:\r\n<UISchema index=\"0\"> ...JSON... </UISchema>\r\n<UISchema index=\"1\"> ...JSON... </UISchema>\r\n</output_formatting>\r\n\r\n<examples>\r\n**Input:**\r\n<GeneratedContent>\r\n<AllowedComponents>div,span,Avatar</AllowedComponents>\r\n<ComponentContext>Avatar [props: { url: string }]</ComponentContext>\r\n<UserContext>grouped under one div</UserContext>\r\n<Value>{ authors: [{ name: \"J.K.\", img: \"...\" }, { name: \"Tolkien\", img: \"...\" }] }</Value>\r\n</GeneratedContent>\r\n\r\n**Correct Output:**\r\n<UISchema index=\"0\">\r\n{\r\n \"type\": \"div\",\r\n \"props\": {\r\n \"className\": \"author-list\"\r\n },\r\n \"children\": [\r\n {\r\n \"type\": \"__ForEach__\",\r\n \"source\": \"authors\",\r\n \"template\": {\r\n \"type\": \"div\",\r\n \"props\": {\r\n \"className\": \"author-card\"\r\n },\r\n \"children\": [\r\n {\r\n \"type\": \"Avatar\",\r\n \"props\": {\r\n \"url\": {\r\n \"$bind\": \"$item.img\"\r\n }\r\n }\r\n },\r\n {\r\n \"type\": \"span\",\r\n \"children\": [\r\n {\r\n \"$bind\": \"$item.name\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n}\r\n</UISchema>\r\n</examples>\r\n\r\n<reasoning_requirements>\r\nBefore generating the JSON, briefly analyze the data structure to identify arrays (requiring `__ForEach__`) and custom component opportunities. Use the mental scratchpad if necessary, but keep the final output strictly within `<UISchema>` tags.\r\n</reasoning_requirements>\r\n\r\n<IMPORTANT>\r\nDo NOT output anything except the UISchema.\r\n</IMPORTANT>","import { isValidElement } from 'react';\r\nimport { GeneratedContentProps, SIGNATURE } from \"./GeneratedContent\";\r\nimport { Renderer, SchemaNode } from \"./Renderer\";\r\nimport { SyntuxComponent, SyntuxElement } from \"./types\";\r\nimport { parseResponse } from \"./util\";\r\nimport { generateText } from \"ai\";\r\nimport systemPrompt from './prompt.md';\r\n\r\nimport { type LanguageModel } from 'ai';\r\n\r\nexport interface GeneratedPageProps {\r\n context?: string;\r\n schema: SyntuxElement;\r\n onGenerate?: (result: SchemaNode[]) => void;\r\n cached?: (SchemaNode | string)[];\r\n}\r\n\r\nfunction extractChildren(element: any) {\r\n if (element?.props?.children) {\r\n let children = element.props.children;\r\n if (!Array.isArray(children)) children = [children];\r\n return children;\r\n }\r\n return [];\r\n}\r\n\r\nfunction searchChildren(element: any, acc: ContentSchema[]) {\r\n const children = extractChildren(element);\r\n\r\n children.forEach((element: SyntuxElement, index: number) => {\r\n if (element?.type.identifier === SIGNATURE) {\r\n const { values, components, hint } = element.props as GeneratedContentProps;\r\n const realComponents: any = []\r\n\r\n if (components) {\r\n components.forEach((comp: string | SyntuxComponent) => {\r\n if (typeof comp === \"string\") {\r\n realComponents.push({\r\n llmName: comp\r\n })\r\n } else {\r\n realComponents.push({\r\n llmName: comp.llmName,\r\n llmContext: comp.llmContext,\r\n userContext: comp.userContext\r\n })\r\n }\r\n })\r\n }\r\n acc.push({\r\n values, components: realComponents, hint: hint || \"\"\r\n })\r\n } else {\r\n searchChildren(element, acc)\r\n }\r\n })\r\n}\r\n\r\nfunction generateInput(content: ContentSchema[], context?: string) {\r\n let str = '';\r\n if (context) {\r\n str = `<PageContext>${context}</PageContext>\\n`;\r\n }\r\n\r\n content.forEach(schema => {\r\n const allowedComponents = schema.components.map(e => e.llmName);\r\n const componentContext: any = []\r\n schema.components.forEach(comp => {\r\n if (comp.llmContext) {\r\n let contextStr;\r\n if (comp.userContext) {\r\n contextStr = `${comp.llmName} [${comp.llmContext}, details: ${comp.userContext}]`\r\n } else {\r\n contextStr = `${comp.llmName} [${comp.llmContext}]`;\r\n }\r\n componentContext.push(contextStr)\r\n }\r\n })\r\n const userContext = schema.hint;\r\n const value = JSON.stringify(schema.values);\r\n\r\n str += `<GeneratedContent>\r\n <AllowedComponents>${allowedComponents.join(',')}</AllowedComponents>\r\n <ComponentContext>${componentContext.join(',')}</ComponentContext>\r\n <UserContext>${userContext}</UserContext>\r\n <Value>${value}</Value>\r\n</GeneratedContent>\\n`\r\n })\r\n\r\n return str;\r\n}\r\n\r\nfunction createComponentRegistry(components: (SyntuxComponent<any> | string)[] | undefined) {\r\n if (!components) return {};\r\n return components.reduce((acc: Record<string, SyntuxComponent<any> | string>, curr: SyntuxComponent<any> | string) => {\r\n if (typeof curr === \"string\") {\r\n acc[curr] = curr;\r\n } else {\r\n if (curr.llmName) {\r\n acc[curr.llmName] = curr;\r\n }\r\n }\r\n return acc;\r\n }, {})\r\n}\r\n\r\nfunction hydrate(schema: SyntuxElement, dsl: (SchemaNode | string)[]) {\r\n let componentIndex = 0;\r\n function swapChildren(element: SyntuxElement) {\r\n const children = extractChildren(element);\r\n\r\n return children.map((child: SyntuxElement, ind: number) => {\r\n if (!isValidElement(child)) return child;\r\n\r\n if (child.type.identifier === SIGNATURE) {\r\n const { values, components, hint } = child.props as GeneratedContentProps;\r\n return <Renderer key={ind} schema={dsl[componentIndex++]} global={values} local={values} components={createComponentRegistry(components)} />\r\n }\r\n\r\n return swapChildren(child);\r\n })\r\n }\r\n\r\n return swapChildren(schema);\r\n}\r\n\r\ninterface ContentSchema {\r\n values: any;\r\n components: { llmContext?: string, userContext?: string, llmName: string }[];\r\n hint: string;\r\n}\r\n\r\nexport const createGeneratedPage = (model: LanguageModel) => {\r\n /**\r\n * Container for content generation. Batches all <GeneratedContent> blocks into one LLM call.\r\n * \r\n * @param context Custom instructions for the LLM about the page, applicable to all components.\r\n * @param schema The structure of the page. Can be a mix of any type of component.\r\n * @param cached User provided React Interface Schema. Will skip schema generation if one is provided.\r\n * @param onGenerate Callback for receiving React Interface Schema after generation, to be used for caching. \r\n */\r\n return async function GeneratedPage({\r\n context, schema, cached, onGenerate\r\n }: GeneratedPageProps) {\r\n if(cached){\r\n return <>{hydrate(schema, cached)}</>\r\n }\r\n\r\n const contents: ContentSchema[] = [];\r\n searchChildren(schema, contents);\r\n\r\n if(contents.length == 0) return schema;\r\n\r\n const llmInput = generateInput(contents, context);\r\n\r\n const { text: llmResponse } = await generateText({\r\n model,\r\n system: systemPrompt,\r\n prompt: llmInput\r\n })\r\n const parsedResponse = parseResponse(llmResponse)\r\n\r\n if(onGenerate){\r\n onGenerate(parsedResponse)\r\n }\r\n \r\n return <>{hydrate(schema, parsedResponse)}</>\r\n }\r\n}","import { LanguageModel } from 'ai';\r\nimport { createGeneratedPage } from './GeneratedPage';\r\nimport { GeneratedContent } from './GeneratedContent';\r\nimport { Renderer } from './Renderer';\r\n\r\nexport { GeneratedContentProps } from './GeneratedContent';\r\nexport { GeneratedPageProps } from './GeneratedPage';\r\nexport {SchemaNode} from './Renderer';\r\n\r\nexport interface SyntuxFactoryConfig {\r\n model: LanguageModel;\r\n}\r\n\r\n\r\nexport const createSyntuxFactory = (config: SyntuxFactoryConfig) => {\r\n return {\r\n GeneratedPage: createGeneratedPage(config.model),\r\n GeneratedContent,\r\n Renderer\r\n }\r\n}"]}
1
+ {"version":3,"sources":["../src/GeneratedContent.tsx","../src/Renderer.tsx","../src/util.ts","../src/prompt.md","../src/GeneratedPage.tsx","../src/index.ts"],"names":["jsx","Fragment"],"mappings":";;;;;AAeO,SAAS,iBAAiB,KAAA,EAA8B;AAM7D,EAAA,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAE,CAAA;AACX;AACO,IAAM,SAAA,0BAAmB,kBAAkB,CAAA;AAClD,gBAAA,CAAiB,UAAA,GAAa,SAAA;ACtB9B,IAAM,WAAA,GAAc,CAAC,GAAA,EAAU,IAAA,KAAiB;AAC5C,EAAA,IAAG,IAAA,KAAS,KAAK,OAAO,GAAA;AACxB,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,EAAK,IAAA,KAAS,GAAA,IAAA,IAAA,GAAA,MAAA,GAAA,GAAA,CAAM,IAAA,CAAA,EAAO,GAAG,CAAA;AACjE,CAAA;AAEA,IAAM,GAAA,GAAM,CAAC,MAAA,EAAa,KAAA,EAAY,IAAA,KAAiB;AACnD,EAAA,IAAG,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,EAAE;AACzB,IAAA,IAAA,GAAO,IAAA,CAAK,MAAM,CAAC,CAAA;AACnB,IAAA,OAAO,WAAA,CAAY,OAAO,IAAI,CAAA;AAAA,EAClC,CAAA,MAAO;AACH,IAAA,IAAG,IAAA,KAAS,SAAS,OAAO,KAAA;AAC5B,IAAA,OAAO,WAAA,CAAY,QAAQ,IAAI,CAAA;AAAA,EACnC;AACJ,CAAA;AAEA,IAAM,YAAA,GAAe,CAAC,MAAA,EAAa,KAAA,EAAY,KAAA,KAAe;AAC1D,EAAA,IAAG,CAAC,KAAA,EAAO;AACX,EAAA,IAAG,WAAW,KAAA,EAAO,OAAO,IAAI,MAAA,EAAQ,KAAA,EAAO,MAAM,KAAK,CAAA;AAC1D,EAAA,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,OAAA,CAAQ,CAAC,GAAA,KAAQ;AAChC,IAAA,MAAM,GAAA,GAAM,MAAM,GAAG,CAAA;AACrB,IAAA,IAAG,OAAO,QAAQ,QAAA,EAAS;AACvB,MAAA,KAAA,CAAM,GAAG,CAAA,GAAI,YAAA,CAAa,MAAA,EAAQ,OAAO,GAAG,CAAA;AAAA,IAChD;AAAA,EACJ,CAAC,CAAA;AACD,EAAA,OAAO,KAAA;AACX,CAAA;AAkBO,SAAS,QAAA,CAAS;AAAA,EACrB,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO;AAC3B,CAAA,EAAkB;AA/ClB,EAAA,IAAA,EAAA;AAgDI,EAAA,IAAG,OAAO,WAAW,QAAA,EAAU,uBAAOA,GAAAA,CAAAC,QAAAA,EAAA,EAAG,QAAA,EAAA,MAAA,EAAO,CAAA;AAChD,EAAA,IAAG,OAAO,KAAA,EAAO;AACb,IAAA,uBAAOD,IAAAC,QAAAA,EAAA,EAAG,cAAI,MAAA,EAAQ,KAAA,EAAO,MAAA,CAAO,KAAK,CAAA,EAAE,CAAA;AAAA,EAC/C;AAEA,EAAA,IAAG,OAAO,IAAA,KAAS,aAAA,IAAiB,MAAA,CAAO,MAAA,IAAU,OAAO,QAAA,EAAS;AACjE,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,MAAA,EAAQ,KAAA,EAAO,OAAO,MAAM,CAAA;AAClD,IAAA,IAAG,CAAC,KAAA,CAAM,OAAA,CAAQ,SAAS,GAAG,OAAO,IAAA;AAErC,IAAA,uBAAOD,IAAAC,QAAAA,EAAA,EACF,oBAAU,GAAA,CAAI,CAAC,MAAM,KAAA,KAAU;AAC5B,MAAA,uBAAOD,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAEJ,QAAQ,MAAA,CAAO,QAAA;AAAA,UACf,MAAA;AAAA,UACA,KAAA,EAAO,IAAA;AAAA,UACP;AAAA,SAAA;AAAA,QAJK;AAAA,OAKT;AAAA,IACJ,CAAC,CAAA,EACL,CAAA;AAAA,EACJ;AAEA,EAAA,IAAG,CAAC,MAAA,CAAO,IAAA,EAAM,OAAO,IAAA;AAExB,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,MAAA,CAAO,IAAI,KAAK,MAAA,CAAO,IAAA;AACpD,EAAA,uBAAOA,GAAAA,CAAC,SAAA,EAAA,EAAW,GAAG,YAAA,CAAa,QAAQ,KAAA,EAAO,MAAA,CAAO,KAAK,CAAA,EACzD,uBAAO,QAAA,KAAP,IAAA,GAAA,MAAA,GAAA,EAAA,CAAiB,GAAA,CAAI,CAAC,MAAM,KAAA,KAAU;AACnC,IAAA,uBAAOA,GAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QAEJ,MAAA,EAAQ,IAAA;AAAA,QACR,MAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OAAA;AAAA,MAJK;AAAA,KAKT;AAAA,EACJ,CAAA,CAAA,EACJ,CAAA;AACJ;;;AClFA,IAAM,YAAA,GAAe,aAAA;AACd,SAAS,cAAc,WAAA,EAAmC;AAC7D,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,KAAA,CAAM,0BAA0B,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,EAAM,CAAA;AACtF,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,MAAM,CAAA,EAAG,CAAC,YAAA,CAAa,MAAM,CAAC,CAAA;AAChE,EAAA,MAAM,SAAS,QAAA,CAAS,GAAA,CAAI,OAAK,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAC9C,EAAA,OAAO,MAAA;AACX;;;ACRA,IAAA,cAAA,GAAA,47PAAA;ACiBA,SAAS,gBAAgB,OAAA,EAAc;AAjBvC,EAAA,IAAA,EAAA;AAkBI,EAAA,IAAA,CAAI,EAAA,GAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,KAAA,KAAT,IAAA,GAAA,MAAA,GAAA,EAAA,CAAgB,QAAA,EAAU;AAC1B,IAAA,IAAI,QAAA,GAAW,QAAQ,KAAA,CAAM,QAAA;AAC7B,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EAAG,QAAA,GAAW,CAAC,QAAQ,CAAA;AAClD,IAAA,OAAO,QAAA;AAAA,EACX;AACA,EAAA,OAAO,EAAC;AACZ;AAEA,SAAS,cAAA,CAAe,SAAwB,GAAA,EAAsB;AAClE,EAAA,IAAG,CAAC,cAAA,CAAe,OAAO,CAAA,EAAG;AAE7B,EAAA,IAAG,OAAA,CAAQ,IAAA,CAAK,UAAA,KAAe,SAAA,EAAU;AACrC,IAAA,MAAM,EAAE,MAAA,EAAQ,UAAA,EAAY,IAAA,KAAS,OAAA,CAAQ,KAAA;AAC7C,IAAA,MAAM,iBAAsB,EAAC;AAE7B,IAAA,IAAI,UAAA,EAAY;AACZ,MAAA,UAAA,CAAW,OAAA,CAAQ,CAAC,IAAA,KAAmC;AACnD,QAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC1B,UAAA,cAAA,CAAe,IAAA,CAAK;AAAA,YAChB,OAAA,EAAS;AAAA,WACZ,CAAA;AAAA,QACL,CAAA,MAAO;AACH,UAAA,cAAA,CAAe,IAAA,CAAK;AAAA,YAChB,SAAS,IAAA,CAAK,OAAA;AAAA,YACd,YAAY,IAAA,CAAK,UAAA;AAAA,YACjB,aAAa,IAAA,CAAK;AAAA,WACrB,CAAA;AAAA,QACL;AAAA,MACJ,CAAC,CAAA;AAAA,IACL;AACA,IAAA,GAAA,CAAI,IAAA,CAAK;AAAA,MACL,MAAA;AAAA,MAAQ,UAAA,EAAY,cAAA;AAAA,MAAgB,MAAM,IAAA,IAAQ;AAAA,KACrD,CAAA;AAAA,EACL,CAAA,MAAO;AACH,IAAA,MAAM,QAAA,GAAW,gBAAgB,OAAO,CAAA;AACxC,IAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,KAAA,KAAyB;AACvC,MAAA,cAAA,CAAe,OAAO,GAAG,CAAA;AAAA,IAC7B,CAAC,CAAA;AAAA,EACL;AACJ;AAEA,SAAS,aAAA,CAAc,SAA0B,OAAA,EAAkB;AAC/D,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,GAAA,GAAM,gBAAgB,OAAO,CAAA;AAAA,CAAA;AAAA,EACjC;AAEA,EAAA,OAAA,CAAQ,QAAQ,CAAA,MAAA,KAAU;AACtB,IAAA,MAAM,oBAAoB,MAAA,CAAO,UAAA,CAAW,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA;AAC9D,IAAA,MAAM,mBAAwB,EAAC;AAC/B,IAAA,MAAA,CAAO,UAAA,CAAW,QAAQ,CAAA,IAAA,KAAQ;AAC9B,MAAA,IAAI,KAAK,UAAA,EAAY;AACjB,QAAA,IAAI,UAAA;AACJ,QAAA,IAAI,KAAK,WAAA,EAAa;AAClB,UAAA,UAAA,GAAa,CAAA,EAAG,KAAK,OAAO,CAAA,EAAA,EAAK,KAAK,UAAU,CAAA,WAAA,EAAc,KAAK,WAAW,CAAA,CAAA,CAAA;AAAA,QAClF,CAAA,MAAO;AACH,UAAA,UAAA,GAAa,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,EAAA,EAAK,KAAK,UAAU,CAAA,CAAA,CAAA;AAAA,QACpD;AACA,QAAA,gBAAA,CAAiB,KAAK,UAAU,CAAA;AAAA,MACpC;AAAA,IACJ,CAAC,CAAA;AACD,IAAA,MAAM,cAAc,MAAA,CAAO,IAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,MAAM,CAAA;AAE1C,IAAA,GAAA,IAAO,CAAA;AAAA,uBAAA,EACU,iBAAA,CAAkB,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,sBAAA,EAC5B,gBAAA,CAAiB,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,iBAAA,EAC/B,WAAW,CAAA;AAAA,WAAA,EACjB,KAAK,CAAA;AAAA;AAAA,CAAA;AAAA,EAEd,CAAC,CAAA;AAED,EAAA,OAAO,GAAA;AACX;AAEA,SAAS,wBAAwB,UAAA,EAA2D;AACxF,EAAA,IAAI,CAAC,UAAA,EAAY,OAAO,EAAC;AACzB,EAAA,OAAO,UAAA,CAAW,MAAA,CAAO,CAAC,GAAA,EAAoD,IAAA,KAAwC;AAClH,IAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC1B,MAAA,GAAA,CAAI,IAAI,CAAA,GAAI,IAAA;AAAA,IAChB,CAAA,MAAO;AACH,MAAA,IAAI,KAAK,OAAA,EAAS;AACd,QAAA,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA,GAAI,IAAA;AAAA,MACxB;AAAA,IACJ;AACA,IAAA,OAAO,GAAA;AAAA,EACX,CAAA,EAAG,EAAE,CAAA;AACT;AAEA,SAAS,OAAA,CAAQ,QAAuB,GAAA,EAA8B;AAClE,EAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,EAAA,SAAS,aAAa,OAAA,EAAwB;AAC1C,IAAA,IAAG,CAAC,cAAA,CAAe,OAAO,CAAA,EAAG,OAAO,OAAA;AAEpC,IAAA,IAAG,OAAA,CAAQ,IAAA,CAAK,UAAA,KAAe,SAAA,EAAU;AACrC,MAAA,MAAM,EAAE,MAAA,EAAQ,UAAA,EAAY,IAAA,KAAS,OAAA,CAAQ,KAAA;AAC7C,MAAA,uBAAOA,GAAAA,CAAC,QAAA,EAAA,EAA8B,MAAA,EAAQ,IAAI,cAAA,EAAgB,CAAA,EAAG,MAAA,EAAQ,MAAA,EAAQ,OAAO,MAAA,EAAQ,UAAA,EAAY,uBAAA,CAAwB,UAAU,KAA5H,cAA+H,CAAA;AAAA,IACzJ;AAGA,IAAA,MAAM,QAAA,GAAW,gBAAgB,OAAO,CAAA;AAExC,IAAA,IAAG,QAAA,CAAS,UAAU,CAAA,EAAE;AACpB,MAAA,OAAO,OAAA;AAAA,IACX;AAEA,IAAA,OAAO,QAAA,CAAS,GAAA,CAAI,CAAC,KAAA,EAAsB,GAAA,KAAgB;AACvD,MAAA,OAAO,aAAa,KAAK,CAAA;AAAA,IAC7B,CAAC,CAAA;AAAA,EACL;AAEA,EAAA,OAAO,aAAa,MAAM,CAAA;AAC9B;AAQO,IAAM,mBAAA,GAAsB,CAAC,KAAA,KAAyB;AASzD,EAAA,OAAO,eAAe,aAAA,CAAc;AAAA,IAChC,OAAA;AAAA,IAAS,MAAA;AAAA,IAAQ,MAAA;AAAA,IAAQ;AAAA,GAC7B,EAAuB;AACnB,IAAA,IAAG,MAAA,EAAO;AACN,MAAA,uBAAOA,GAAAA,CAAAC,QAAAA,EAAA,EAAG,QAAA,EAAA,OAAA,CAAQ,MAAA,EAAQ,MAAM,CAAA,EAAE,CAAA;AAAA,IACtC;AAEA,IAAA,MAAM,WAA4B,EAAC;AACnC,IAAA,cAAA,CAAe,QAAQ,QAAQ,CAAA;AAC/B,IAAA,OAAA,CAAQ,GAAA,CAAI,YAAY,QAAQ,CAAA;AAEhC,IAAA,IAAG,QAAA,CAAS,MAAA,IAAU,CAAA,EAAG,OAAO,MAAA;AAEhC,IAAA,MAAM,QAAA,GAAW,aAAA,CAAc,QAAA,EAAU,OAAO,CAAA;AAEhD,IAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAY,GAAI,MAAM,YAAA,CAAa;AAAA,MAC7C,KAAA;AAAA,MACA,MAAA,EAAQ,cAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACX,CAAA;AACD,IAAA,MAAM,cAAA,GAAiB,cAAc,WAAW,CAAA;AAEhD,IAAA,IAAG,UAAA,EAAW;AACV,MAAA,UAAA,CAAW,cAAc,CAAA;AAAA,IAC7B;AAEA,IAAA,uBAAOD,GAAAA,CAAAC,QAAAA,EAAA,EAAG,QAAA,EAAA,OAAA,CAAQ,MAAA,EAAQ,cAAc,CAAA,EAAE,CAAA;AAAA,EAC9C,CAAA;AACJ,CAAA;;;ACjKO,IAAM,mBAAA,GAAsB,CAAC,MAAA,KAAgC;AAChE,EAAA,OAAO;AAAA,IACH,aAAA,EAAe,mBAAA,CAAoB,MAAA,CAAO,KAAK,CAAA;AAAA,IAC/C,gBAAA;AAAA,IACA;AAAA,GACJ;AACJ","file":"index.mjs","sourcesContent":["import { ComponentType } from 'react'\r\nimport { SyntuxComponent } from './types';\r\n\r\nexport interface GeneratedContentProps {\r\n values: any;\r\n components?: (SyntuxComponent<any> | string)[];\r\n hint?: string;\r\n}\r\n\r\n/**\r\n * Section of user interface for LLM to generate.\r\n * @param values The values (object, primitive, or array) to be displayed.\r\n * @param components List of allowed components that LLM can use.\r\n * @param hint Additional custom instructions for the LLM.\r\n */\r\nexport function GeneratedContent(props: GeneratedContentProps) {\r\n /**\r\n * This is an empty component.\r\n * It acts as a declarative slot that <GeneratedPage> recognizes\r\n * and replaces with a Renderer during hydration.\r\n */\r\n return <></>;\r\n}\r\nexport const SIGNATURE = Symbol('GeneratedContent');\r\nGeneratedContent.identifier = SIGNATURE;","import { ComponentType } from 'react'\r\n\r\nconst resolvePath = (obj: any, path: string) => {\r\n if(path === '$') return obj;\r\n return path.split('.').reduce((acc, curr) => acc?.[curr], obj)\r\n}\r\n\r\nconst get = (global: any, local: any, path: string) => {\r\n if(path.startsWith(\"$item.\")){\r\n path = path.slice(6)\r\n return resolvePath(local, path);\r\n } else {\r\n if(path === \"$item\") return local;\r\n return resolvePath(global, path);\r\n }\r\n}\r\n\r\nconst resolveProps = (global: any, local: any, props: any) => {\r\n if(!props) return;\r\n if(\"$bind\" in props) return get(global, local, props.$bind); // $bind may be falsy value\r\n Object.keys(props).forEach((key) => {\r\n const val = props[key];\r\n if(typeof val === \"object\"){\r\n props[key] = resolveProps(global, local, val);\r\n }\r\n })\r\n return props;\r\n}\r\n\r\nexport interface SchemaNode {\r\n type?: string;\r\n props?: Record<string, any>;\r\n children?: (SchemaNode | string)[];\r\n source?: string;\r\n template?: SchemaNode;\r\n $bind?: string;\r\n}\r\n\r\nexport interface RendererProps {\r\n schema: SchemaNode | string; // string occurs recursively\r\n global: any;\r\n local?: any;\r\n components: Record<string, ComponentType<any> | string>;\r\n}\r\n\r\nexport function Renderer({\r\n schema, global, local, components\r\n}: RendererProps) {\r\n if(typeof schema === \"string\") return <>{schema}</>;\r\n if(schema.$bind) {\r\n return <>{get(global, local, schema.$bind)}</>\r\n }\r\n\r\n if(schema.type === '__ForEach__' && schema.source && schema.template){\r\n const sourceArr = get(global, local, schema.source);\r\n if(!Array.isArray(sourceArr)) return null;\r\n\r\n return <>\r\n {sourceArr.map((item, index) => {\r\n return <Renderer\r\n key={index}\r\n schema={schema.template!}\r\n global={global}\r\n local={item}\r\n components={components}\r\n />\r\n })}\r\n </>\r\n }\r\n\r\n if(!schema.type) return null;\r\n\r\n const Component = components[schema.type] || schema.type;\r\n return <Component {...resolveProps(global, local, schema.props)}>\r\n {schema.children?.map((item, index) => {\r\n return <Renderer\r\n key={index}\r\n schema={item}\r\n global={global}\r\n local={local}\r\n components={components}\r\n />\r\n })}\r\n </Component>\r\n}\r\n","import { SchemaNode } from \"./Renderer\"\r\n\r\nconst endDelimiter = \"</UISchema>\"\r\nexport function parseResponse(llmResponse: string): SchemaNode[] {\r\n const split = llmResponse.split(/\\<UISchema index=\"\\d+\">/m).slice(1).map(e => e.trim())\r\n const contents = split.map(e => e.slice(0, -endDelimiter.length));\r\n const parsed = contents.map(e => JSON.parse(e))\r\n return parsed\r\n}","<system_persona>\r\nYou are the **UI Schema Generation Engine**, a specialized architect responsible for converting raw data structures into abstract, reusable React Interface Schemas (JSON-DSL).\r\n\r\nYour output is **NOT** code. Your output is a JSON-based Abstract Syntax Tree (AST) that describes the UI structure. The rendering engine will hydrate this schema with data later.\r\n</system_persona>\r\n\r\n<core_philosophy>\r\n1. **Separation of Concerns:** You define the *structure*. You do NOT hardcode *values*.\r\n2. **Strict Adherence:** You may ONLY use components explicitly listed in the `<AllowedComponents>` block of the input. If the block is missing or empty, revert to the <default_component_library>.\r\n3. **Semantic Structure:** Even though you are generating JSON, the resulting UI must be semantically correct (using proper hierarchy, semantic HTML tags, and logical grouping).\r\n4. **Reusability:** Your schema must be valid regardless of the specific values in the data. It must handle list lengths of 0 or 1000 gracefully using the Iterator Protocol.\r\n</core_philosophy>\r\n\r\n<dsl_syntax_rules>\r\nThe output must be a JSON object adhering to this strict recursive interface:\r\n\r\n### 1. The Standard Node\r\nUsed for HTML tags or Custom Components.\r\n```json\r\n{\r\n \"type\": \"div\" | \"h1\" | \"MyCustomComponent\",\r\n \"props\": { \"className\": \"...\", \"customProp\": \"...\" },\r\n \"children\": [] // Array of Nodes or Strings\r\n}\r\n```\r\n\r\n### 2. The Binding Protocol (`$bind`)\r\n\r\n**NEVER** output raw data values (e.g., \"John\", \"john@email.com\") in the schema.\r\nInstead, bind to a path.\r\n\r\n```json\r\n// BAD\r\n{ \"type\": \"span\", \"children\": [\"John\"] }\r\n\r\n// GOOD\r\n{ \"type\": \"span\", \"children\": [{ \"$bind\": \"user.firstName\" }] }\r\n```\r\n\r\nYou have access to exactly **two scopes** at any time:\r\n- **Global Scope (Root)**: Any path **WITHOUT** the `$item` prefix accesses the top-level global data object. This is available at any nesting depth.\r\n - *Example:* `\"$bind\": \"pageTitle\"` (Always looks at `data.pageTitle`)\r\n- **Local Scope (Current Item):** Any path **STARTING WITH** `$item` accesses the immediate object currently being iterated in a loop.\r\n - *Example:* `\"$bind\": \"$item.name\"` (Looks at `name` on the current loop item).\r\n - *Example:* `\"$bind\": \"$item\"` (Renders the current loop item, usually a string).\r\n\r\nIn special cases, you may need to reference a specific, fixed index in an array. To do that, use dot notation to access the index. For instance: `arr.1.property` accesses the `property` property of the 2nd item in `arr`. However, use this conservatively; prefer to use the Iterator Protocol unless it doesn't make sense (e.g., it's a static array).\r\n\r\n**CRITICAL:** Intermediate scopes are not accessible. Inside a nested loop, `$item` refers *only* to the innermost item.\r\n\r\n### 3. The Iterator Protocol (`__ForEach__`)\r\n\r\nIf the data value is an Array, you MUST use this node. Do not manually unroll lists.\r\n\r\n- **Root Arrays**: If the input value is the array itself, use \"source\": \"$\".\r\n- **Nested Arrays**: If the array is a property on the current item, use `\"source\": \"$item.path.to.array\"`.\r\n- **Global Arrays**: If the array is a property on the Global Root, use `\"source\": \"path.to.array\"`.\r\n\r\n```json\r\n{\r\n \"type\": \"__ForEach__\",\r\n \"source\": \"$\" | \"$item.path.to.array\" | \"path.to.array\",\r\n \"template\": {\r\n // This is the shape of a SINGLE item.\r\n // Inside here, use \"$item\" to refer to the current array element.\r\n \"type\": \"li\",\r\n \"children\": [{ \"$bind\": \"$item.name\" }]\r\n }\r\n}\r\n```\r\n\r\n</dsl_syntax_rules>\r\n\r\n<default_component_library>\r\nIf no specific allowed components are provided, you have access to this semantic HTML suite:\r\n\r\n * **Layout:** `div`, `section`, `article`, `main`, `aside`, `header`, `footer`\r\n * **Typography:** `h1`, `h2`, `h3`, `p`, `span`, `strong`, `em`, `blockquote`, `pre`, `code`\r\n * **Lists:** `ul`, `ol`, `li`\r\n * **Interaction:** `button`, `a` (use href prop), `details`, `summary`\r\n * **Form:** `input`, `label`, `textarea`, `select`, `option`\r\n * **Media:** `img`, `figure`, `figcaption`\r\n\r\n</default_component_library>\r\n\r\n<input_processing_rules>\r\nThe user will provide one or more `<GeneratedContent>` blocks.\r\n\r\n1. **Parse `AllowedComponents`:** A comma-separated list.\r\n * Lowercase = Native HTML tags.\r\n * Uppercase = Custom React Components.\r\n2. **Parse `ComponentContext`:** Defines the TypeScript interface for Custom Components.\r\n * *CRITICAL:* You must strictly adhere to the prop names and types defined here. Do not hallucinate props for custom components.\r\n * Components are separated by a comma, in the format `ComponentName [props: { ... }, details: \"...\"]`. The `props` indicate what `props` it must accept, in Typescript format. The `details` is an optional field, and describes what the component does. Use this information in whatever way to improve your generation output. If you encounter a complex type in `props`, look at the input values and make your best guess at what value is the best fit.\r\n3. **Parse `UserContext`:** This is anything the developer believes is relevant for your task. It could describe a specific UI style or the correct way to use a custom component.\r\n * *CRITICAL*: To the best of your ability, respect the developer's wishes. If no UserContext is provided, you should accomplish the task as you see fit, with no constraints.\r\n * *CRITICAL*: This is only relevant to the current <GeneratedContent> block!\r\n3. **Parse `Value`:** The JSON data structure you are building the UI for.\r\n\r\nAdditionally, the user may provide a <PageContext> before all <GeneratedContent> blocks. Think of this as a global UserContext. This is meant to provide additional context and guiding when designing the UI, which you should try to adhere to. If none is provided, accomplish the task as you see fit, with no constraints.\r\n\r\n</input_processing_rules>\r\n\r\n<output_formatting>\r\nFor every `<GeneratedContent>` input block, you must generate exactly one `<UISchema>` output block.\r\nThe order must be preserved.\r\n\r\nInput:\r\n<PageContext></PageContext>\r\n<GeneratedContent> ... </GeneratedContent> (Section 1)\r\n<GeneratedContent> ... </GeneratedContent> (Section 2)\r\n\r\nOutput:\r\n<UISchema index=\"0\"> ...JSON... </UISchema>\r\n<UISchema index=\"1\"> ...JSON... </UISchema>\r\n</output_formatting>\r\n\r\n<examples>\r\n**Input:**\r\n<GeneratedContent>\r\n<AllowedComponents>div,span,Avatar</AllowedComponents>\r\n<ComponentContext>Avatar [props: { url: string }]</ComponentContext>\r\n<UserContext>grouped under one div</UserContext>\r\n<Value>{ authors: [{ name: \"J.K.\", img: \"...\" }, { name: \"Tolkien\", img: \"...\" }] }</Value>\r\n</GeneratedContent>\r\n\r\n**Correct Output:**\r\n<UISchema index=\"0\">\r\n{\r\n \"type\": \"div\",\r\n \"props\": {\r\n \"className\": \"author-list\"\r\n },\r\n \"children\": [\r\n {\r\n \"type\": \"__ForEach__\",\r\n \"source\": \"authors\",\r\n \"template\": {\r\n \"type\": \"div\",\r\n \"props\": {\r\n \"className\": \"author-card\"\r\n },\r\n \"children\": [\r\n {\r\n \"type\": \"Avatar\",\r\n \"props\": {\r\n \"url\": {\r\n \"$bind\": \"$item.img\"\r\n }\r\n }\r\n },\r\n {\r\n \"type\": \"span\",\r\n \"children\": [\r\n {\r\n \"$bind\": \"$item.name\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n}\r\n</UISchema>\r\n</examples>\r\n\r\n<reasoning_requirements>\r\nBefore generating the JSON, briefly analyze the data structure to identify arrays (requiring `__ForEach__`) and custom component opportunities. Use the mental scratchpad if necessary, but keep the final output strictly within `<UISchema>` tags.\r\n</reasoning_requirements>\r\n\r\n<IMPORTANT>\r\nDo NOT output anything except the UISchema.\r\n</IMPORTANT>","import { isValidElement } from 'react';\r\nimport { GeneratedContentProps, SIGNATURE } from \"./GeneratedContent\";\r\nimport { Renderer, SchemaNode } from \"./Renderer\";\r\nimport { SyntuxComponent, SyntuxElement } from \"./types\";\r\nimport { parseResponse } from \"./util\";\r\nimport { generateText } from \"ai\";\r\nimport systemPrompt from './prompt.md';\r\n\r\nimport { type LanguageModel } from 'ai';\r\n\r\nexport interface GeneratedPageProps {\r\n context?: string;\r\n schema: SyntuxElement;\r\n onGenerate?: (result: SchemaNode[]) => void;\r\n cached?: (SchemaNode | string)[];\r\n}\r\n\r\nfunction extractChildren(element: any) {\r\n if (element?.props?.children) {\r\n let children = element.props.children;\r\n if (!Array.isArray(children)) children = [children];\r\n return children;\r\n }\r\n return [];\r\n}\r\n\r\nfunction searchChildren(element: SyntuxElement, acc: ContentSchema[]) {\r\n if(!isValidElement(element)) return;\r\n\r\n if(element.type.identifier === SIGNATURE){\r\n const { values, components, hint } = element.props as GeneratedContentProps;\r\n const realComponents: any = []\r\n\r\n if (components) {\r\n components.forEach((comp: string | SyntuxComponent) => {\r\n if (typeof comp === \"string\") {\r\n realComponents.push({\r\n llmName: comp\r\n })\r\n } else {\r\n realComponents.push({\r\n llmName: comp.llmName,\r\n llmContext: comp.llmContext,\r\n userContext: comp.userContext\r\n })\r\n }\r\n })\r\n }\r\n acc.push({\r\n values, components: realComponents, hint: hint || \"\"\r\n })\r\n } else {\r\n const children = extractChildren(element);\r\n children.forEach((child: SyntuxElement) => {\r\n searchChildren(child, acc)\r\n })\r\n }\r\n}\r\n\r\nfunction generateInput(content: ContentSchema[], context?: string) {\r\n let str = '';\r\n if (context) {\r\n str = `<PageContext>${context}</PageContext>\\n`;\r\n }\r\n\r\n content.forEach(schema => {\r\n const allowedComponents = schema.components.map(e => e.llmName);\r\n const componentContext: any = []\r\n schema.components.forEach(comp => {\r\n if (comp.llmContext) {\r\n let contextStr;\r\n if (comp.userContext) {\r\n contextStr = `${comp.llmName} [${comp.llmContext}, details: ${comp.userContext}]`\r\n } else {\r\n contextStr = `${comp.llmName} [${comp.llmContext}]`;\r\n }\r\n componentContext.push(contextStr)\r\n }\r\n })\r\n const userContext = schema.hint;\r\n const value = JSON.stringify(schema.values);\r\n\r\n str += `<GeneratedContent>\r\n <AllowedComponents>${allowedComponents.join(',')}</AllowedComponents>\r\n <ComponentContext>${componentContext.join(',')}</ComponentContext>\r\n <UserContext>${userContext}</UserContext>\r\n <Value>${value}</Value>\r\n</GeneratedContent>\\n`\r\n })\r\n\r\n return str;\r\n}\r\n\r\nfunction createComponentRegistry(components: (SyntuxComponent<any> | string)[] | undefined) {\r\n if (!components) return {};\r\n return components.reduce((acc: Record<string, SyntuxComponent<any> | string>, curr: SyntuxComponent<any> | string) => {\r\n if (typeof curr === \"string\") {\r\n acc[curr] = curr;\r\n } else {\r\n if (curr.llmName) {\r\n acc[curr.llmName] = curr;\r\n }\r\n }\r\n return acc;\r\n }, {})\r\n}\r\n\r\nfunction hydrate(schema: SyntuxElement, dsl: (SchemaNode | string)[]) {\r\n let componentIndex = 0;\r\n function swapChildren(element: SyntuxElement) {\r\n if(!isValidElement(element)) return element;\r\n\r\n if(element.type.identifier === SIGNATURE){\r\n const { values, components, hint } = element.props as GeneratedContentProps;\r\n return <Renderer key={componentIndex} schema={dsl[componentIndex++]} global={values} local={values} components={createComponentRegistry(components)} />;\r\n }\r\n\r\n\r\n const children = extractChildren(element);\r\n\r\n if(children.length == 0){\r\n return element;\r\n }\r\n\r\n return children.map((child: SyntuxElement, ind: number) => {\r\n return swapChildren(child);\r\n })\r\n }\r\n\r\n return swapChildren(schema);\r\n}\r\n\r\ninterface ContentSchema {\r\n values: any;\r\n components: { llmContext?: string, userContext?: string, llmName: string }[];\r\n hint: string;\r\n}\r\n\r\nexport const createGeneratedPage = (model: LanguageModel) => {\r\n /**\r\n * Container for content generation. Batches all <GeneratedContent> blocks into one LLM call.\r\n * \r\n * @param context Custom instructions for the LLM about the page, applicable to all components.\r\n * @param schema The structure of the page. Can be a mix of any type of component.\r\n * @param cached User provided React Interface Schema. Will skip schema generation if one is provided.\r\n * @param onGenerate Callback for receiving React Interface Schema after generation, to be used for caching. \r\n */\r\n return async function GeneratedPage({\r\n context, schema, cached, onGenerate\r\n }: GeneratedPageProps) {\r\n if(cached){\r\n return <>{hydrate(schema, cached)}</>\r\n }\r\n\r\n const contents: ContentSchema[] = [];\r\n searchChildren(schema, contents);\r\n console.log('contents', contents);\r\n \r\n if(contents.length == 0) return schema;\r\n\r\n const llmInput = generateInput(contents, context);\r\n\r\n const { text: llmResponse } = await generateText({\r\n model,\r\n system: systemPrompt,\r\n prompt: llmInput\r\n })\r\n const parsedResponse = parseResponse(llmResponse)\r\n\r\n if(onGenerate){\r\n onGenerate(parsedResponse)\r\n }\r\n \r\n return <>{hydrate(schema, parsedResponse)}</>\r\n }\r\n}","import { LanguageModel } from 'ai';\r\nimport { createGeneratedPage } from './GeneratedPage';\r\nimport { GeneratedContent } from './GeneratedContent';\r\nimport { Renderer } from './Renderer';\r\n\r\nexport { GeneratedContentProps } from './GeneratedContent';\r\nexport { GeneratedPageProps } from './GeneratedPage';\r\nexport {SchemaNode} from './Renderer';\r\n\r\nexport interface SyntuxFactoryConfig {\r\n model: LanguageModel;\r\n}\r\n\r\n\r\nexport const createSyntuxFactory = (config: SyntuxFactoryConfig) => {\r\n return {\r\n GeneratedPage: createGeneratedPage(config.model),\r\n GeneratedContent,\r\n Renderer\r\n }\r\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getsyntux",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "The deterministic generative-UI library.",
5
5
  "exports": {
6
6
  ".": {