UNPKG

@adonis-agora/agent

Version:

Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.

100 lines • 7.39 kB
/** * The app's design system inside the sandbox — the isomorphic half: what the kit docs look like, * what the model is told about them, what the browser is told about the assets, and the script that * draws the model's JSX in the frame. The Node half (docs generation, the bundle, the Vite plugin, * discovery) is `genui/kit`. */ import { SANDBOX_JSX_FRAME_SOURCE } from './sandbox-jsx-frame-generated.js'; /** What the opt-in assets weigh: fetched once per page, handed to (or inlined into) every frame that uses them. */ export const SANDBOX_ASSET_SIZES = { /** `@tailwindcss/browser` v4 (minified, as inlined; ≈75 KB gzipped over the wire, once). */ tailwind: '≈280 KB', /** React + ReactDOM in the kit bundle, before the app's own components. */ kit: '≈230 KB + your components', }; /** A prop's line in the model text: `variant?: "default" | "outline" = "default" — the look`. */ function propLine(prop) { const type = prop.type.length > 160 ? `${prop.type.slice(0, 157)}…` : prop.type; return `${prop.name}${prop.required ? '' : '?'}: ${type}${prop.default !== undefined ? ` = ${prop.default}` : ''}${prop.description ? ` — ${prop.description.replace(/\s+/g, ' ').slice(0, 140)}` : ''}`; } /** The kit as the model reads it: one entry per component, its props from their types. */ export function kitDocsToModelText(docs) { const lines = [ 'Kit components (the app design system — use these first; each is in scope by name, and on the global `Kit`):', ]; for (const component of docs.components) { const head = `- <${component.name}>${component.description ? ` ${component.description.replace(/\s+/g, ' ').slice(0, 200)}` : ''}`; lines.push(head); for (const prop of component.props) lines.push(` ${propLine(prop)}`); if (component.inherits !== undefined) lines.push(` …and every <${component.inherits}> attribute (className, onClick, …)`); } return lines.join('\n'); } /** The rules for writing the sandbox as JSX. */ export function kitJsxInstructions(options = {}) { const components = options.components !== false; return [ 'Write the view as JSX in `jsx` (instead of `html`/`jsFunctions`): plain JavaScript + JSX, no TypeScript, no imports — define `function App()` and return the UI; it is rendered for you.', components ? 'React hooks (useState, useEffect, useMemo, useRef, useCallback, useReducer) and every kit component are in scope by name. Use kit components for controls and surfaces, plain elements for the rest.' : 'React hooks (useState, useEffect, useMemo, useRef, useCallback, useReducer) are in scope by name; use plain elements.', ...(options.wrapper === true ? [ "App is rendered inside the app's own providers (its theme, its baseline styles): do not add a theme provider or global resets of your own.", ] : []), 'Keep state in App; call agent.send({ text, ...values }) from a click handler to hand values back.', 'Write the view in jsx OR in html, never both: leave the other one empty.', ].join(' '); } /** The rule for a kit with styles but no components: the model writes HTML with those styles. */ export function kitHtmlInstructions() { return 'There is no component kit here: write html (and jsFunctions/jsExpressions), never jsx.'; } /** * The script that draws the model's JSX in the frame: it holds the transpiler, compiles what the * host posts (`{ type: jsxMessage, code, final }`), runs it in a scope with the kit components and * React's hooks, and renders `App` into `#agora-sandbox-root`. A partial program is drawn only once * it closes into code that parses and renders; until then — and whenever a later version fails — * the last good one stays on screen. Errors are reported (to the host) only for the final program. * A partial program is not tried before its JSX has begun (nothing to draw before then). */ export function sandboxJsxRuntime(options) { const t = JSON.stringify(options.token); const type = JSON.stringify(options.jsxMessage); const initial = options.initial === undefined ? 'null' : JSON.stringify(options.initial); // The transpiler ships prebuilt as a string (never `fn.toString()` of bundled code, which a // consumer's minifier rewrites): see scripts/build-frame-runtime.mjs. return `(function(){${SANDBOX_JSX_FRAME_SOURCE};var transpileJsx=__genuiJsx.transpileJsx,prepareSandboxJsx=__genuiJsx.prepareSandboxJsx; var T=${t},TYPE=${type},R=window.React,D=window.ReactDOM,K=window.Kit||{},W=typeof window.KitWrapper==='function'||(window.KitWrapper&&typeof window.KitWrapper==='object')?window.KitWrapper:null; if(window.__GENUI_KIT_CSS__){var ks=document.createElement('style');ks.textContent=window.__GENUI_KIT_CSS__;document.head.appendChild(ks)} var kitNames=Object.keys(K).filter(function(k){return /^[A-Z][\\w$]*$/.test(k)}); var hookNames=['useState','useEffect','useMemo','useRef','useCallback','useReducer','useId','useLayoutEffect','Fragment'].filter(function(k){return R&&R[k]!==undefined}); var root=null,lastGood=null,seq=0,lastCode=null; window.addEventListener('error',function(e){if(window.__agoraQuiet){e.preventDefault();e.stopImmediatePropagation()}},true); function report(e){window.__agoraQuiet=false;try{window.dispatchEvent(new ErrorEvent('error',{message:String(e&&e.message||e)}))}catch(_){}} var Boundary=R?(function(){function B(p){R.Component.call(this,p);this.state={failed:false}} B.prototype=Object.create(R.Component.prototype);B.prototype.constructor=B; B.getDerivedStateFromError=function(){return{failed:true}}; B.prototype.componentDidCatch=function(e){if(this.props.final)report(e)}; B.prototype.componentDidMount=function(){if(!this.state.failed)lastGood=this.props.app}; B.prototype.render=function(){if(this.state.failed)return this.props.keep?R.createElement(this.props.keep):null;return this.props.children}; return B})():null; function draw(code,final){if(!R||!D)return false;if(code===lastCode&&!final)return true; if(!final&&!/(return|=>)\\s*\\(?\\s*</.test(code))return false;var js; try{js=transpileJsx(prepareSandboxJsx(code),{partial:!final})}catch(e){if(final)report(e);return false} window.__genuiApp=undefined;window.__genuiOk=false;window.__agoraQuiet=!final; var s=document.createElement('script'); s.textContent='(function(){var Kit=window.Kit||{},React=window.React;var {'+kitNames.join(',')+'}=Kit;var {'+hookNames.join(',')+'}=React;(function(){\\n'+js+'\\n;window.__genuiApp=typeof App==="function"?App:undefined})()})();window.__genuiOk=true;'; document.head.appendChild(s);s.remove();window.__agoraQuiet=false; if(!window.__genuiOk||typeof window.__genuiApp!=='function'){return false} lastCode=code;var App=window.__genuiApp; if(!root)root=D.createRoot(document.getElementById('agora-sandbox-root')); var view=R.createElement(Boundary,{key:++seq,app:App,keep:lastGood,final:final},R.createElement(App));\nroot.render(W?R.createElement(W,null,view):view); return true} window.addEventListener('message',function(e){if(e.source!==window.parent)return;var d=e.data;if(!d||d.token!==T||d.type!==TYPE)return;draw(String(d.code||''),d.final===true)}); var init=${initial};if(init){draw(init.code,init.final)}})();`; } //# sourceMappingURL=sandbox-kit.js.map