Class: PromptObjects::Universal::RenderArtifact
- Inherits:
-
Primitive
- Object
- Capability
- Primitive
- PromptObjects::Universal::RenderArtifact
- Defined in:
- lib/prompt_objects/universal/render_artifact.rb
Overview
Universal capability to render interactive HTML in the UI artifact panel. Artifacts are environment-wide — any PO can create or update any artifact.
Modes:
replace (default) — updates existing artifact with the same title in place
version — always creates a new artifact entry
The frontend renders artifacts in a sandboxed iframe with React 18, Tailwind CSS, and Babel (for JSX) available.
Artifacts are bidirectional (BURP — Bidirectional UI Rendering Protocol): a PromptObjects.send(message) function is injected into every artifact. Calling it sends a natural-language message back to the PO that rendered the artifact (provenance "artifact:
Instance Attribute Summary
Attributes inherited from Capability
Instance Method Summary collapse
Methods inherited from Primitive
Methods inherited from Capability
#descriptor, execution_policy, execution_policy_definition, #execution_policy_definition, #execution_policy_signature, #initialize, #resolved_execution_policy
Constructor Details
This class inherits a constructor from PromptObjects::Primitive
Instance Method Details
#description ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/prompt_objects/universal/render_artifact.rb', line 34 def description "Render an interactive HTML/JSX artifact in the UI panel. The sandboxed iframe ALREADY provides " \ "React 18, ReactDOM, Babel, and Tailwind, plus a <div id='root'> mount point. " \ "IMPORTANT: send ONLY your component markup — do NOT include <html>/<head>/<body> wrappers or your " \ "own <script src=...> CDN tags for React/Babel/Tailwind (the iframe provides them; your own copies " \ "conflict). Do NOT use `import` or `export` (it is not an ES module; those silently fail to render). " \ "Put JSX in <script type='text/babel'>, define a component, and you MUST mount it yourself with: " \ "ReactDOM.createRoot(document.getElementById('root')).render(<App />); " \ "BIDIRECTIONAL: PromptObjects.send('...') is available inside the artifact — wire it to " \ "buttons/forms/controls so the human can talk back to YOU through the UI instead of chatting " \ "(messages arrive from 'artifact:<title>'). Respond to them by re-rendering this artifact " \ "(mode 'replace') with the updated UI. A re-render resets the artifact's local JS state, so " \ "bake the current state into the HTML you render. " \ "Default mode is 'replace' — same title updates in place. Use mode 'version' for a new entry each time." end |
#name ⇒ Object
30 31 32 |
# File 'lib/prompt_objects/universal/render_artifact.rb', line 30 def name "render_artifact" end |
#parameters ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/prompt_objects/universal/render_artifact.rb', line 50 def parameters { type: "object", properties: { title: { type: "string", description: "Short title for the artifact tab. In replace mode, this is the unique identifier — same title overwrites the previous version." }, html: { type: "string", description: "Your component markup only — NOT a full page. React 18/ReactDOM/Babel/Tailwind " \ "and a <div id='root'> are already provided by the iframe; do NOT add <html>/<head>/<body> " \ "or your own <script src=...> CDN tags. No `import`/`export`. Put JSX in <script type='text/babel'> " \ "and END with a mount, e.g.: function App(){return <div className='p-4'>…</div>} " \ "ReactDOM.createRoot(document.getElementById('root')).render(<App />); — without that mount nothing shows." }, mode: { type: "string", enum: %w[replace version], description: "replace (default): update existing artifact with same title. version: always create a new artifact entry." } }, required: %w[title html] } end |
#receive(message, context:) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/prompt_objects/universal/render_artifact.rb', line 76 def receive(, context:) title = [:title] || ["title"] html = [:html] || ["html"] mode = [:mode] || ["mode"] || "replace" return "Error: 'title' is required" unless title return "Error: 'html' is required" unless html return "Error: artifact persistence is unavailable" unless context.env.respond_to?(:persist_artifact) context.env.persist_artifact(title: title, html: html, mode: mode, context: context) "Artifact '#{title}' rendered (#{mode}) in the UI." end |