From 396b0edd9ee0ed0d9a885db1ab6ba199650a363b Mon Sep 17 00:00:00 2001 From: ahmed mohammed Date: Tue, 22 Sep 2026 07:54:52 +0300 Subject: [PATCH] feat: openui report library Co-Authored-By: Claude Opus 4.7 --- lib/report-ui.ts | 127 ++++++++++++++++++++++++++++++++++++++++ tests/report-ui.test.ts | 11 ++++ 2 files changed, 138 insertions(+) create mode 100644 lib/report-ui.ts create mode 100644 tests/report-ui.test.ts diff --git a/lib/report-ui.ts b/lib/report-ui.ts new file mode 100644 index 0000000..585cc92 --- /dev/null +++ b/lib/report-ui.ts @@ -0,0 +1,127 @@ +import { createElement as el, type ReactNode } from "react"; +import { defineComponent, createLibrary } from "@openuidev/react-lang"; +import { z } from "zod/v4"; + +// No JSX in this file on purpose: `node --test` imports it, and Node strips types but not JSX. +// el(type, props, ...children) is createElement with the noise removed. +const p = (style: Record, ...kids: ReactNode[]) => el("p", { style }, ...kids); +const muted = { color: "var(--qai-ink-muted)" } as const; +const small = { fontSize: "var(--qai-text-xs)", color: "var(--qai-ink-muted)" } as const; +const disp = { fontFamily: "var(--qai-font-display)" } as const; + +const Headline = defineComponent({ name: "Headline", + description: "Report title: the one-line finding, with severity.", + props: z.object({ title: z.string(), subtitle: z.string().optional(), + severity: z.enum(["critical", "warning", "info"]).optional() }), + component: ({ props }) => el("header", null, + el("p", { className: "label" }, props.severity === "critical" ? "Critical" : props.severity === "warning" ? "Warning" : "Note"), + el("h2", { style: { ...disp, fontSize: "var(--qai-text-2xl)", margin: "var(--qai-space-s) 0" } }, props.title), + props.subtitle ? p(muted, props.subtitle) : null) }); + +const Metric = defineComponent({ name: "Metric", description: "One plan metric.", + props: z.object({ label: z.string(), value: z.string(), note: z.string().optional() }), + component: ({ props }) => el("div", { className: "card" }, + el("p", { className: "label" }, props.label), + p({ ...disp, fontSize: "var(--qai-text-xl)" }, props.value), + props.note ? p(small, props.note) : null) }); + +const MetricGrid = defineComponent({ name: "MetricGrid", description: "Row of plan metrics.", + props: z.object({ items: z.array(Metric.ref) }), + component: ({ props, renderNode }) => el("div", { className: "grid-metrics" }, renderNode(props.items)) }); + +const Finding = defineComponent({ name: "Finding", description: "One problem, the plan evidence for it, its impact.", + props: z.object({ where: z.string(), issue: z.string(), evidence: z.string(), impact: z.string() }), + component: ({ props }) => el("div", { className: "card" }, + el("p", { className: "label" }, props.where), + p({ margin: "var(--qai-space-s) 0" }, el("strong", null, props.issue)), + el("p", { className: "sql" }, props.evidence), + p(muted, props.impact)) }); + +const Findings = defineComponent({ name: "Findings", description: "Everything wrong with the plan.", + props: z.object({ items: z.array(Finding.ref) }), + component: ({ props, renderNode }) => el("section", { className: "report" }, renderNode(props.items)) }); + +const Step = defineComponent({ name: "Step", description: "One action step.", + props: z.object({ text: z.string(), effort: z.enum(["low", "medium", "high"]).optional(), + owner: z.enum(["dba", "developer", "both"]).optional(), changeControl: z.boolean().optional() }), + component: ({ props }) => el("li", { className: "card", style: { display: "flex", gap: "var(--qai-space-md)", + alignItems: "center", flexWrap: "wrap" } }, + el("span", { style: { flex: "1 1 200px", minWidth: 0 } }, props.text), + props.effort ? el("span", { className: "pill" }, `effort ${props.effort}`) : null, + props.owner ? el("span", { className: "pill" }, props.owner) : null, + props.changeControl ? el("span", { className: "pill" }, "change control") : null) }); + +const StepList = defineComponent({ name: "StepList", description: "Ordered action plan for one option.", + props: z.object({ title: z.string(), steps: z.array(Step.ref) }), + component: ({ props, renderNode }) => el("section", null, + el("h3", { style: disp }, props.title), + el("ol", { style: { listStyle: "none", padding: 0, margin: 0, display: "grid", gap: "var(--qai-space-md)" } }, + renderNode(props.steps))) }); + +const SqlBlock = defineComponent({ name: "SqlBlock", description: "A SQL snippet the user can copy.", + props: z.object({ title: z.string(), sql: z.string(), caption: z.string().optional() }), + component: ({ props }) => el("figure", { className: "card", style: { margin: 0 } }, + el("figcaption", { className: "label" }, props.title), + el("pre", { className: "sql" }, props.sql), + el("button", { className: "btn no-print", onClick: () => navigator.clipboard.writeText(props.sql) }, "Copy SQL"), + props.caption ? el("p", { style: small }, props.caption) : null) }); + +const ScoreBar = defineComponent({ name: "ScoreBar", description: "One Jev dimension: normalised value plus confidence.", + props: z.object({ label: z.string(), value: z.number(), confidence: z.number().optional(), note: z.string().optional() }), + component: ({ props }) => el("div", null, + el("p", { className: "label" }, props.label + (props.confidence !== undefined + ? ` · confidence ${props.confidence.toFixed(2)}` : " · no confidence reported")), + el("div", { className: "bar", style: { width: `${Math.round(props.value * 100)}%` } }), + props.note ? el("p", { style: small }, props.note) : null) }); + +const OptionRow = defineComponent({ name: "OptionRow", description: "One ranked option.", + props: z.object({ rank: z.number(), title: z.string(), composite: z.number(), headline: z.boolean(), + flags: z.string().optional() }), + component: ({ props }) => el("tr", { "data-headline": props.headline || undefined }, + el("td", null, String(props.rank)), el("td", null, props.title), + el("td", { className: "sql" }, props.composite.toFixed(2)), + el("td", null, props.flags || "—")) }); + +const OptionTable = defineComponent({ name: "OptionTable", description: "All options ranked by composite score.", + props: z.object({ title: z.string(), weights: z.string(), rows: z.array(OptionRow.ref) }), + component: ({ props, renderNode }) => el("section", { className: "card" }, + el("h3", { style: disp }, props.title), + el("p", { style: small }, props.weights), + el("table", { style: { width: "100%", borderCollapse: "collapse" } }, el("tbody", null, renderNode(props.rows)))) }); + +const VerdictBlock = defineComponent({ name: "VerdictBlock", description: "What Jev decided, and how sure it was.", + props: z.object({ headline: z.string(), why: z.string(), source: z.enum(["jev", "composite"]), confidence: z.number() }), + component: ({ props }) => el("section", { className: "card", "data-verdict": "" }, + el("p", { className: "label" }, "First move · " + (props.source === "jev" + ? `Jev, confidence ${props.confidence.toFixed(2)}` : "composite order — Jev did not decide")), + p({ ...disp, fontSize: "var(--qai-text-lg)" }, props.headline), + p({}, props.why)) }); + +const Callout = defineComponent({ name: "Callout", description: "A warning or note the user must not miss.", + props: z.object({ level: z.enum(["info", "warn", "danger", "success"]), title: z.string(), text: z.string() }), + component: ({ props }) => el("div", { className: "card", "data-level": props.level, + role: props.level === "danger" ? "alert" : "note" }, + el("p", null, el("strong", null, props.title)), el("p", null, props.text)) }); + +const Report = defineComponent({ name: "Report", description: "Root. A query-plan report in reading order.", + props: z.object({ blocks: z.array(z.union([Headline.ref, VerdictBlock.ref, MetricGrid.ref, Findings.ref, + OptionTable.ref, StepList.ref, SqlBlock.ref, ScoreBar.ref, Callout.ref])) }), + component: ({ props, renderNode }) => el("div", { className: "report", id: "report" }, renderNode(props.blocks)) }); + +export const library = createLibrary({ root: "Report", components: [Headline, Metric, MetricGrid, Finding, Findings, + Step, StepList, SqlBlock, ScoreBar, OptionRow, OptionTable, VerdictBlock, Callout, Report] }); + +export const reportPromptOptions = { + preamble: "You output only OpenUI Lang. No prose, no markdown fences, no commentary before or after.", + additionalRules: [ + "root = Report([...]) and it must list every block you define.", + "Block order: Headline, VerdictBlock, MetricGrid, Findings, OptionTable, then per option its StepList and SqlBlock, then ScoreBars, then Callout.", + "Use ONLY numbers present in the input. Never invent a cost, row count, impact, or confidence.", + "One SqlBlock per rewrite, titled with that option's key. T-SQL only, no markdown.", + "Every option flagged verify_semantics gets a Callout level danger: compare result rows before deploying.", + "If verdict.source is composite, say plainly that Jev did not decide.", + ], + examples: [`root = Report([head, verdict]) +head = Headline("Clustered Index Scan on Sales.Orders is 84% of the plan", "No usable key on CustomerId", "critical") +verdict = VerdictBlock("Create the covering index", "bottleneck_fit 1.00, semantic_safety 1.00, ease 0.50.", "jev", 0.82)`], +}; diff --git a/tests/report-ui.test.ts b/tests/report-ui.test.ts new file mode 100644 index 0000000..bc092de --- /dev/null +++ b/tests/report-ui.test.ts @@ -0,0 +1,11 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +const { library, reportPromptOptions } = await import("../lib/report-ui.ts"); + +test("the prompt advertises every component and the root", () => { + const p = library.prompt(reportPromptOptions); + for (const n of ["Report", "Headline", "VerdictBlock", "MetricGrid", "Findings", "OptionTable", + "StepList", "SqlBlock", "ScoreBar", "Callout"]) assert.ok(p.includes(n), `missing ${n}`); + assert.match(p, /root/i); + assert.match(p, /never invent/i); +});