Frontend Labs
⋯

public/agent-ui.js

// The "actionable UI" layer (§61): the agent never sends HTML. It sends
// { component, props } and this registry decides what may be rendered,
// validates every prop, and wires actions to app code it controls.

// h(): build DOM with createElement + text nodes only. Under the page's
// Trusted Types policy any innerHTML assignment would throw (§65).
export function h(tag, attrs = {}, ...children) {
  const el = document.createElement(tag);
  for (const [k, v] of Object.entries(attrs)) {
    if (k.startsWith("on") && typeof v === "function") el.addEventListener(k.slice(2), v);
    else if (v === true) el.setAttribute(k, "");
    else if (v !== false && v != null) el.setAttribute(k, String(v));
  }
  for (const c of children.flat()) {
    if (c != null && c !== false) el.append(c instanceof Node ? c : document.createTextNode(String(c)));
  }
  return el;
}

const money = (n) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(n);

const orderSchema = { id: "string", item: "string", total: "number", status: "string" };

const registry = {
  "order-card": {
    schema: orderSchema,
    render: (o) =>
      h("article", { class: "order-card", "aria-label": `Order ${o.id}` },
        h("strong", {}, o.id), " ", o.item,
        h("div", { class: "meta" }, money(o.total), " · ", h("span", { class: "status" }, o.status))),
  },
  "refund-approval": {
    schema: orderSchema,
    render: (o, { actions }) => {
      const status = h("p", { class: "status", role: "status" });
      const approve = h("button", {
        type: "button",
        onclick: async () => {
          approve.disabled = decline.disabled = true;
          try {
            await actions.requestRefund(o.id);
            status.textContent = `Refund requested for ${o.id}.`;
          } catch (err) {
            status.textContent = `Refund failed: ${err.message}`;
            approve.disabled = decline.disabled = false;
          }
        },
      }, `Approve refund of ${money(o.total)}`);
      const decline = h("button", {
        type: "button", class: "secondary",
        onclick: () => {
          approve.disabled = decline.disabled = true;
          status.textContent = "Refund declined. Nothing was changed.";
        },
      }, "Decline");
      return h("article", { class: "order-card approval", "aria-label": `Approve refund for ${o.id}` },
        h("strong", {}, o.id), " ", o.item, h("div", { class: "actions" }, approve, decline), status);
    },
  },
};

function validate(schema, props) {
  if (typeof props !== "object" || props === null) return null;
  const clean = {};
  for (const [key, type] of Object.entries(schema)) {
    if (typeof props[key] !== type) return null; // wrong or missing: refuse the whole component
    clean[key] = props[key];
  }
  return clean; // unknown props are dropped
}

export function renderComponent({ component, props }, ctx) {
  const def = Object.hasOwn(registry, component) ? registry[component] : null;
  const clean = def && validate(def.schema, props);
  if (!clean) {
    console.warn("agent-ui: refused component", component);
    return null;
  }
  return def.render(clean, ctx);
}

Generated from SOURCE.md · 8 Oct 2026 16:36