Files
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

1157 lines
40 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { XuluxTemplate } from "@/components/xulux/templates/types";
import { getDemoDownloadManifest } from "@/lib/xulux/demo-downloads/manifest";
// ---------------------------------------------------------------------------
// Agent-facing static metadata (selection + authoring hints per template id)
// These are agent-facing descriptions, not catalog/runtime metadata.
// Shared by the Xulux chat route tools and the public MCP catalog endpoint.
// ---------------------------------------------------------------------------
export type TemplateListMeta = {
name: string;
summary: string;
assistantPlacement: string;
features: string[];
customizable: string[];
};
export const TEMPLATE_LIST_META: Record<string, TemplateListMeta> = {
"base-assistant-ui": {
name: "Configurable Base Assistant UI",
summary:
"A hosted configurable version of the assistant-ui Base demo with the same full-page chat shell, thread list, composer, model picker, mic input, suggestions, slash commands, and no-key demo flows.",
assistantPlacement: "full-page chat shell",
features: [
"assistant-ui Base demo layout with sidebar thread list and centered composer",
"Composer actions including attachments, model picker, send, and mic input",
"LocalStorage thread persistence with Assistant Cloud fallback when configured in source",
"Controlled suggestion groups and slash commands",
"Deterministic demo flows when no model key is present",
"Hosted preview sessions and downloadable materialized starter app",
],
customizable: [
"brandTheme: preset plus accent, background, surface, and text hex overrides",
"assistant: appName, welcome headline/body, composer placeholder, new-thread/new-chat labels",
"assistant.suggestionGroups: controlled icon ids and prompt options with optional flowId",
"assistant.slashCommands: controlled icon ids",
"assistant.tools and assistant.demoFlows for no-key mock behavior",
],
},
"webpage-assistant": {
name: "Webpage with Assistant",
summary:
"A full-page docs or website layout with a sidebar or modal assistant. Pages are defined in config and the assistant can search, preview, and generate code snippets grounded in those pages.",
assistantPlacement: "sidebar (desktop) / modal (mobile)",
features: [
"ContentShell layout: header, left nav, article area, right assistant sidebar",
"assistant-ui Thread in sidebar on desktop, AssistantModal on mobile",
"Three built-in tools: searchDocs (sourceResults card), openPage (pagePreview card), generateCodeSnippet (codeSnippet card)",
"Deterministic demo flows: scripted tool sequences run without an API key",
"Suggested prompt chips wired to demo flows",
],
customizable: [
"hostUi: productName, docsName, defaultPageId, assistantPlacement, navGroups, pages (id/title/section/description/url/markdown/keywords/relatedPageIds)",
"assistant: productName, docsName, assistantName, welcome (headline/body), labels (10 UI strings), demoModeNotice, suggestedPrompts, tools (id/displayName/aiDescription/realImplementationHint/rendererType), demoFlows (auth401/webhooks/codeExample steps)",
"brandTheme: accent, surface, border, mutedText, focusRing",
],
},
"product-page-assistant": {
name: "Product Page with Floating Assistant",
summary:
"A mock product dashboard with a floating modal support assistant. The dashboard is a configurable JSON component tree. The assistant runs a two-step analyze-then-handoff flow.",
assistantPlacement: "floating modal (bottom-right)",
features: [
"DashboardShell layout: nav, alert banner, configurable panel tree",
"Panel components: Overview, MetricGrid + MetricCard, TwoColumnRow, StatusList, ActivityFeed",
"assistant-ui AssistantModal as a floating trigger button",
"Two built-in tools: analyzeIssue (analysis card), createSupportSummary (summary card)",
"Deterministic demo flows keyed by scenarioId (sync_failure, auth_error)",
"File attachment support (mock) in demo flows",
],
customizable: [
"hostUi: full DashboardShell component tree (NOT deep-merged — provide complete tree)",
"assistant: companyName, productName, assistantName, welcome (badge/title/subtitle), labels, demoModeNotice, agentPrompt (persona/instructions/responseStyle), toolCardLabels, toolCardDesign, suggestedPrompts, tools, demoFlows",
"assistant.toolData: serviceOptions, mockAccountStatus, escalationLabels, priorityLabels, scenarioPacks",
"brandTheme: accent, surface, border, mutedText, success, warning, destructive, focusRing",
],
},
};
export function fixedDemoListMeta(
entry: XuluxTemplate,
): TemplateListMeta | undefined {
const demo = getDemoDownloadManifest(entry.id);
if (!demo) {
if (entry.id === "expo-react-native") {
return {
name: entry.title,
summary: entry.description,
assistantPlacement: "hosted Expo web preview",
features: [
"Expo / React Native mobile chat UI",
"Drawer navigation and thread management",
"Streaming assistant responses through assistant-ui runtime",
"Native mobile UI primitives, with hosted web preview for inspection",
],
customizable: [],
};
}
return undefined;
}
return {
name: demo.name,
summary: demo.description,
assistantPlacement: "full-page demo route",
features: demo.features,
customizable: [],
};
}
export const CONFIG_ROOTS_SCHEMAS: Record<string, Record<string, unknown>> = {
"base-assistant-ui": {
brandTheme: {
description:
"Controls the Base chat visual theme. Use a preset first, then optional 6-digit hex overrides for key surfaces.",
schema: {
preset: {
type: "string",
enum: [
"assistantDark",
"assistantLight",
"neutralDark",
"neutralLight",
],
default: "assistantDark",
optional: true,
},
accent: {
type: "string",
optional: true,
description: "6-digit hex color such as #14b8a6.",
},
background: {
type: "string",
optional: true,
description: "6-digit hex color for the main background.",
},
surface: {
type: "string",
optional: true,
description: "6-digit hex color for sidebar and composer surfaces.",
},
text: {
type: "string",
optional: true,
description: "6-digit hex color for primary foreground text.",
},
},
},
assistant: {
description:
"Controls visible Base chat labels, welcome copy, suggestions, slash commands, generic tools, and deterministic no-key demo flows. Omit fields you do not want to change.",
schema: {
appName: {
type: "string",
default: "assistant-ui",
description: "Visible app name in the sidebar.",
},
welcome: {
headline: {
type: "string",
default: "How can I help you today?",
},
body: {
type: "string",
optional: true,
description: "Optional supporting welcome text.",
},
},
labels: {
type: "object",
optional: true,
fields: {
composerPlaceholder: {
type: "string",
default: "Send a message... (@ to mention, / for commands)",
},
newThread: { type: "string", default: "New Thread" },
newChat: { type: "string", default: "New Chat" },
},
},
suggestionGroups: {
type: "array",
description:
"Suggestion buttons shown under the composer. Use only supported icon ids.",
item: {
id: { type: "string" },
label: { type: "string" },
icon: {
type: "string",
optional: true,
enum: [
"weather",
"code",
"write",
"analyze",
"brainstorm",
"search",
"document",
"help",
],
},
options: {
type: "array",
item: {
label: { type: "string" },
prompt: { type: "string" },
flowId: {
type: "string",
optional: true,
description:
"When present, should match a key in assistant.demoFlows.",
},
},
},
},
},
slashCommands: {
type: "array",
optional: true,
description:
"Slash-command menu entries. Use only supported icon ids.",
item: {
id: { type: "string" },
description: { type: "string" },
icon: {
type: "string",
optional: true,
enum: ["FileText", "Languages", "Globe", "HelpCircle"],
},
},
},
tools: {
type: "array",
optional: true,
description:
"Generic demo tools available to no-key demo flows. Custom ids are supported and render as generic tool cards.",
item: {
id: { type: "string" },
displayName: { type: "string" },
aiDescription: { type: "string" },
rendererType: {
type: "string",
enum: ["generic"],
default: "generic",
optional: true,
},
},
},
demoFlows: {
type: "object",
optional: true,
description:
"Keyed by flow id. A suggestion option can trigger a flow through options[].flowId. Each step can call one configured generic tool.",
valueSchema: {
title: { type: "string", optional: true },
triggerPhrases: {
type: "array",
optional: true,
items: "string",
},
steps: {
type: "array",
item: {
id: { type: "string" },
assistantText: { type: "string" },
toolId: {
type: "string",
description: "Must match an id in assistant.tools.",
},
input: { type: "object" },
output: { type: "object" },
},
},
finalResponse: { type: "string" },
},
},
demoModeNotice: {
type: "string",
optional: true,
description:
"Short notice shown when deterministic demo mode is used.",
},
},
},
},
"webpage-assistant": {
hostUi: {
description:
"Controls the visible page — product name, docs name, navigation, and all page content. All pages the assistant can open or reference must be defined here. Deep-merged with template defaults.",
schema: {
version: { type: "number", value: 1, description: "Always 1." },
root: {
type: {
type: "string",
value: "ContentShell",
description: "Fixed — do not change.",
},
props: {
productName: {
type: "string",
default: "OrbitKit API",
description: "Product name shown in the top nav.",
},
docsName: {
type: "string",
default: "OrbitKit Docs",
description: "Docs workspace label shown below product name.",
},
defaultPageId: {
type: "string",
default: "quickstart",
description:
"Id of the page shown on first load. Must be one of the ids in pages.",
},
assistantPlacement: {
type: "string",
enum: ["sidebar", "modal"],
default: "sidebar",
optional: true,
description: "Where the assistant appears on desktop.",
},
navGroups: {
type: "array",
optional: true,
description:
"Groups pages under section labels in the left nav. If omitted, pages are listed flat.",
item: {
label: {
type: "string",
description: "Section label shown in the nav.",
},
pageIds: {
type: "array",
items: "string",
description: "Page ids in this group. Must exist in pages.",
},
},
},
pages: {
type: "array",
description:
"All content pages. Must include the page with defaultPageId.",
item: {
id: {
type: "string",
description:
"Unique page id. Referenced by defaultPageId, navGroups, and demo flow steps.",
},
title: {
type: "string",
description: "Page title shown in nav and article header.",
},
section: {
type: "string",
description: "Nav section label this page belongs to.",
},
description: {
type: "string",
description: "Short description shown in search results.",
},
url: {
type: "string",
description: "Canonical URL path for the page.",
},
markdown: {
type: "string",
description: "Full page content in markdown.",
},
keywords: {
type: "array",
items: "string",
description: "Search keywords for this page.",
},
relatedPageIds: {
type: "array",
items: "string",
description: "Ids of related pages. Must exist in pages.",
},
},
},
},
},
},
},
assistant: {
description:
"Controls the thread experience — identity, welcome, labels, suggested prompts, tools, demo flows, and demo mode notice. Deep-merged with template defaults — only include fields you want to override.",
schema: {
productName: { type: "string", default: "OrbitKit API" },
docsName: { type: "string", default: "OrbitKit Docs" },
assistantName: { type: "string", default: "Docs Copilot" },
welcome: {
headline: { type: "string", default: "Ask about these docs" },
body: {
type: "string",
default:
"I can search the docs, preview pages, and generate implementation snippets from the current article.",
},
},
labels: {
type: "object",
optional: true,
description:
"UI label overrides. All fields optional — omit any to keep the default.",
fields: {
currentPage: { type: "string", default: "Current page" },
source: { type: "string", default: "Source" },
relatedPages: { type: "string", default: "Related pages" },
openPage: { type: "string", default: "Open in preview" },
headerSearch: {
type: "string",
default: "Search docs with the assistant",
},
articleCtaTitle: {
type: "string",
default: "Need a targeted answer?",
},
articleCtaBody: {
type: "string",
default:
"Use the assistant to search these docs with this page as context.",
},
articleCtaAction: { type: "string", default: "Ask in sidebar" },
composerPlaceholder: {
type: "string",
default:
"Ask about auth, webhooks, errors, or the current page...",
},
previewWarning: {
type: "string",
default:
"Preview config could not be loaded. Showing default template.",
},
},
},
demoModeNotice: {
type: "string",
optional: true,
default:
"Demo mode is deterministic because no OPENAI_API_KEY is set. Add a key to enable live model responses.",
},
suggestedPrompts: {
type: "array",
description: "Prompt chips shown on thread open. 14 items.",
item: {
title: { type: "string" },
description: { type: "string", optional: true },
prompt: { type: "string" },
flowId: {
type: "string",
optional: true,
enum: ["auth401", "webhooks", "codeExample"],
},
},
},
tools: {
type: "array",
description:
"Tools registered in the assistant. Built-in ids (searchDocs, openPage, generateCodeSnippet) have specialized renderers. Custom ids use generic.",
item: {
id: { type: "string" },
displayName: { type: "string" },
aiDescription: { type: "string" },
realImplementationHint: { type: "string" },
rendererType: {
type: "string",
enum: ["sourceResults", "pagePreview", "codeSnippet", "generic"],
},
},
},
demoFlows: {
type: "object",
description:
"Keyed by flow id. Each flow runs in demo mode or when a matching prompt chip is clicked.",
keys: ["auth401", "webhooks", "codeExample"],
valueSchema: {
title: { type: "string" },
triggerPhrases: { type: "array", items: "string" },
steps: {
type: "array",
item: {
id: { type: "string" },
assistantText: { type: "string" },
toolId: {
type: "string",
description: "Must match an id in assistant.tools.",
},
input: {
type: "object",
description: "Must match the tool's input shape.",
},
output: {
type: "object",
description:
"Must match the tool's outputShape for the renderer to display correctly.",
},
},
},
finalResponse: { type: "string" },
},
},
},
},
brandTheme: {
description: "Color tokens shared across the page and thread.",
schema: {
accent: { type: "string", default: "#0369a1" },
surface: { type: "string", default: "#ffffff" },
border: { type: "string", default: "#dbe3ea" },
mutedText: { type: "string", default: "#64748b" },
focusRing: { type: "string", default: "#38bdf8" },
},
},
},
"product-page-assistant": {
hostUi: {
description:
"Controls the visible dashboard page — shell layout, nav, and all panel content. hostUi is NOT deep-merged. Provide the complete tree whenever you include this root.",
schema: {
version: { type: "number", value: 1, description: "Always 1." },
root: {
type: {
type: "string",
value: "DashboardShell",
description: "Fixed — do not change.",
},
props: {
productName: { type: "string", default: "Northstar Sync" },
companyName: { type: "string", default: "Northstar Cloud" },
workspaceLabel: { type: "string", default: "Workspace" },
accountName: { type: "string", default: "Acme Operations" },
accountMeta: { type: "string", default: "Scale plan, us-west" },
alertText: {
type: "string",
optional: true,
default: "Workflow attention needed in us-west",
description: "Omit to hide the alert banner.",
},
navItems: {
type: "array",
items: "string",
default: ["Overview", "Workflows", "Records", "Assistant"],
},
},
children: {
type: "array",
description:
"Panel components inside the shell. Supported: Overview, MetricGrid+MetricCard, TwoColumnRow, StatusList, ActivityFeed.",
supportedNodes: {
Overview: {
props: {
title: "string",
subtitle: "string",
status: "string",
},
},
MetricGrid: { description: "Wrapper for MetricCard children." },
MetricCard: {
props: { label: "string", value: "string", trend: "string" },
},
TwoColumnRow: {
description:
"Fixed two-column dashboard row. Place StatusList or ActivityFeed as children.",
},
StatusList: {
props: {
title: "string",
items: [
{ name: "string", state: "string", detail: "string" },
],
},
},
ActivityFeed: { props: { title: "string", items: ["string"] } },
},
},
},
},
},
assistant: {
description:
"Controls the floating modal thread — identity, welcome, labels, tools, demo flows, and support routing data. Deep-merged with template defaults — only include fields you want to override.",
schema: {
companyName: { type: "string", default: "Northstar Cloud" },
productName: { type: "string", default: "Northstar Sync" },
assistantName: { type: "string", default: "Northstar Support" },
welcome: {
badge: { type: "string", default: "Screenshots and logs supported" },
title: { type: "string", default: "Get support for your workspace" },
subtitle: {
type: "string",
default:
"Describe the issue, attach a screenshot or log, and I will prepare a support handoff.",
},
},
labels: {
type: "object",
optional: true,
description:
"Free-form string record. Any key overrides the matching default label.",
commonKeys: {
modalTrigger: { default: "Open support" },
composerPlaceholder: {
default: "Describe the issue or attach a screenshot/log...",
},
escalationCta: { default: "Ready for support handoff" },
loading: { default: "Preparing support handoff..." },
success: { default: "Handoff ready" },
},
},
demoModeNotice: {
type: "string",
optional: true,
default:
"Demo note: This is a mock support demo. Add OPENAI_API_KEY to .env.local to use real AI and connect your own tools.",
},
agentPrompt: {
persona: {
type: "string",
default: "a support troubleshooting assistant",
},
instructions: {
type: "string",
default:
"When enough context exists, use the available tools to analyze the issue and prepare a support handoff. Ask a concise follow-up only when the issue is too vague.",
},
responseStyle: {
type: "string",
default:
"Keep responses customer-facing, concise, and handoff-ready.",
},
},
toolCardLabels: {
type: "object",
optional: true,
description:
"Display name overrides for built-in tool result cards. Keyed by tool id.",
default: {
analyzeIssue: "Issue analysis",
createSupportSummary: "Support summary",
},
},
toolCardDesign: {
type: "object",
optional: true,
description: "Visual style options for tool result cards.",
fields: {
density: {
type: "string",
enum: ["compact", "default"],
default: "compact",
},
iconSet: { type: "string", enum: ["lucide"], default: "lucide" },
statusBadgeStyle: {
type: "string",
enum: ["solid", "outline"],
default: "solid",
},
ticketSummaryLayout: {
type: "string",
enum: ["handoff", "default"],
default: "handoff",
},
},
},
suggestedPrompts: {
type: "array",
description: "Prompt chips shown on modal open. 14 items.",
item: {
title: { type: "string" },
label: { type: "string" },
prompt: { type: "string" },
scenarioId: {
type: "string",
enum: ["sync_failure", "auth_error"],
},
},
},
tools: {
type: "array",
description:
"Built-in ids (analyzeIssue, createSupportSummary) have specialized renderers. Custom ids use generic.",
item: {
id: { type: "string" },
displayName: { type: "string" },
aiDescription: { type: "string" },
realImplementationHint: { type: "string" },
rendererType: {
type: "string",
enum: ["analysis", "summary", "generic"],
},
},
},
demoFlows: {
type: "object",
description:
"Keyed by scenarioId. Runs in demo mode or when a matching prompt chip is clicked.",
keys: ["sync_failure", "auth_error"],
valueSchema: {
finalResponse: { type: "string" },
steps: {
type: "array",
item: {
id: { type: "string" },
toolId: {
type: "string",
description: "Must match an id in assistant.tools.",
},
assistantText: { type: "string" },
input: {
type: "object",
description: "Must match the tool's input shape.",
},
output: {
type: "object",
description:
"Must match the tool's outputShape for the renderer to display correctly.",
},
},
},
},
},
toolData: {
description:
"Support routing data used by demo flows and tool handlers.",
schema: {
serviceOptions: {
type: "array",
items: "string",
default: [
"Primary workflow",
"User access",
"Data source",
"Notifications",
"API",
],
},
mockAccountStatus: {
accountName: { type: "string", default: "Acme Operations" },
plan: { type: "string", default: "Scale" },
region: { type: "string", default: "us-west" },
accountHealth: { type: "string", default: "Active" },
},
escalationLabels: {
defaultOwner: { type: "string", default: "Tier 2 Sync Support" },
defaultSla: {
type: "string",
default: "First response within 2 business hours",
},
},
priorityLabels: {
P1: { type: "string", default: "Critical" },
P2: { type: "string", default: "High" },
P3: { type: "string", default: "Normal" },
},
scenarioPacks: {
type: "array",
description:
"One pack per demo scenario. Seeds mock analysis and summary outputs.",
item: {
id: { type: "string", enum: ["sync_failure", "auth_error"] },
title: { type: "string" },
triggerPhrases: { type: "array", items: "string" },
defaultAffectedService: { type: "string" },
mockAttachments: { type: "array", items: "string" },
firstResponse: { type: "string" },
analysis: {
category: "string",
likelyCause: "string",
severity: "low|medium|high",
explanation: "string",
nextStep: "string",
},
summary: {
ticketId: "string",
priority: "P1|P2|P3",
customerImpact: "string",
recommendedOwner: "string",
nextResponseSla: "string",
},
},
},
},
},
},
},
brandTheme: {
description: "Color tokens shared across the dashboard and thread.",
schema: {
accent: { type: "string", default: "#2563eb" },
surface: { type: "string", default: "#ffffff" },
border: { type: "string", default: "#d8dee8" },
mutedText: { type: "string", default: "#64748b" },
success: { type: "string", default: "#15803d" },
warning: { type: "string", default: "#b45309" },
destructive: { type: "string", default: "#b91c1c" },
focusRing: { type: "string", default: "#3b82f6" },
},
},
},
};
export type TemplateToolsMeta = {
builtIn: Array<{
id: string;
description: string;
renderer: string;
input: Record<string, unknown>;
outputShape: Record<string, unknown>;
}>;
customToolSupported: boolean;
renderers: Array<{
type: string;
description: string;
requiredOutputShape: unknown;
}>;
};
export const TOOLS_META: Record<string, TemplateToolsMeta> = {
"base-assistant-ui": {
builtIn: [
{
id: "getWeather",
description: "Demo weather lookup tool used by the default Base flow.",
renderer: "generic",
input: {
city: { type: "string", required: true },
units: {
type: "string",
required: false,
enum: ["fahrenheit", "celsius"],
},
},
outputShape: {
city: "string",
summary: "string",
temperature: "string",
wind: "string",
},
},
{
id: "inspectCode",
description: "Demo code helper tool used by the default Base flow.",
renderer: "generic",
input: {
language: { type: "string", required: true },
topic: { type: "string", required: true },
},
outputShape: {
language: "string",
notes: ["string"],
},
},
{
id: "draftContent",
description: "Demo writing helper tool used by the default Base flow.",
renderer: "generic",
input: {
format: { type: "string", required: true },
tone: { type: "string", required: false },
},
outputShape: {
outline: ["string"],
},
},
{
id: "compareItems",
description: "Demo analysis helper tool used by the default Base flow.",
renderer: "generic",
input: {
criteria: { type: "array", required: true, items: "string" },
},
outputShape: {
columns: ["string"],
rows: "number",
},
},
{
id: "brainstormIdeas",
description:
"Demo brainstorming helper tool used by the default Base flow.",
renderer: "generic",
input: {
count: { type: "number", required: true },
grouping: { type: "string", required: false },
},
outputShape: {
themes: ["string"],
count: "number",
},
},
],
customToolSupported: true,
renderers: [
{
type: "generic",
description:
"Fallback assistant-ui tool card rendering configured tool input and output as structured data.",
requiredOutputShape: "any JSON-serializable value",
},
],
},
"webpage-assistant": {
builtIn: [
{
id: "searchDocs",
description: "Searches configured pages and returns matching results.",
renderer: "sourceResults",
input: {
query: {
type: "string",
required: true,
description: "Search query string.",
},
limit: { type: "number", required: false, default: 3 },
},
outputShape: {
query: "string",
results: [
{
pageId: "string",
title: "string",
section: "string",
url: "string",
snippet: "string",
score: "number",
},
],
},
},
{
id: "openPage",
description: "Opens a specific page by id and returns its metadata.",
renderer: "pagePreview",
input: {
pageId: {
type: "string",
required: true,
description: "Must match an id in hostUi.root.props.pages.",
},
},
outputShape: {
pageId: "string",
title: "string",
section: "string",
url: "string",
description: "string",
relatedPageIds: ["string"],
},
},
{
id: "generateCodeSnippet",
description: "Generates a code snippet grounded in docs context.",
renderer: "codeSnippet",
input: {
topic: { type: "string", required: true },
language: {
type: "string",
required: false,
enum: ["curl", "typescript", "python"],
default: "typescript",
},
},
outputShape: {
topic: "string",
language: "string",
code: "string",
notes: ["string"],
docsUrl: "string",
},
},
],
customToolSupported: true,
renderers: [
{
type: "sourceResults",
description:
"List of page result cards showing title, section, snippet, and open link.",
requiredOutputShape: {
query: "string",
results: [
{
pageId: "string",
title: "string",
section: "string",
url: "string",
snippet: "string",
score: "number",
},
],
},
},
{
type: "pagePreview",
description:
"Single page card with title, section, description, and related page links.",
requiredOutputShape: {
pageId: "string",
title: "string",
section: "string",
url: "string",
description: "string",
relatedPageIds: ["string"],
},
},
{
type: "codeSnippet",
description:
"Syntax-highlighted code block with topic, language badge, notes, and docs link.",
requiredOutputShape: {
topic: "string",
language: "string",
code: "string",
notes: ["string"],
docsUrl: "string",
},
},
{
type: "generic",
description:
"Fallback collapsible card rendering any tool output as JSON.",
requiredOutputShape: "any",
},
],
},
"product-page-assistant": {
builtIn: [
{
id: "analyzeIssue",
description:
"Analyzes the issue and returns severity, likely cause, affected service, and next step.",
renderer: "analysis",
input: {
description: { type: "string", required: true },
service: { type: "string", required: true },
attachments: {
type: "array",
required: false,
items: { name: "string", type: "string" },
},
scenarioId: {
type: "string",
required: true,
enum: ["sync_failure", "auth_error"],
},
},
outputShape: {
category: "string",
confidence: "number",
likelyCause: "string",
affectedService: "string",
severity: "low|medium|high",
explanation: "string",
nextStep: "string",
followUpQuestions: ["string"],
attachments: [{ name: "string", type: "string" }],
},
},
{
id: "createSupportSummary",
description:
"Creates a structured handoff summary card from the issue analysis.",
renderer: "summary",
input: {
issue: {
type: "object",
required: true,
description: "The full output of analyzeIssue.",
},
attachments: {
type: "array",
required: false,
items: { name: "string", type: "string" },
},
scenarioId: {
type: "string",
required: true,
enum: ["sync_failure", "auth_error"],
},
},
outputShape: {
ticketId: "string",
priority: "P1|P2|P3",
customerImpact: "string",
summary: "string",
recommendedOwner: "string",
nextResponseSla: "string",
attachments: ["string"],
},
},
],
customToolSupported: true,
renderers: [
{
type: "analysis",
description:
"Issue analysis card showing severity badge, likely cause, affected service, explanation, next step, and follow-up questions.",
requiredOutputShape: {
category: "string",
confidence: "number",
likelyCause: "string",
affectedService: "string",
severity: "string",
explanation: "string",
nextStep: "string",
followUpQuestions: ["string"],
},
},
{
type: "summary",
description:
"Handoff summary card showing ticket id, priority, customer impact, recommended owner, and SLA.",
requiredOutputShape: {
ticketId: "string",
priority: "string",
customerImpact: "string",
summary: "string",
recommendedOwner: "string",
nextResponseSla: "string",
},
},
{
type: "generic",
description:
"Fallback collapsible card rendering any tool output as JSON.",
requiredOutputShape: "any",
},
],
},
};
export const RULES: Record<string, string[]> = {
"base-assistant-ui": [
"Top-level config should use only assistant and brandTheme.",
"brandTheme color overrides must be 6-digit hex colors such as #14b8a6.",
"assistant.suggestionGroups[].icon must be one of weather, code, write, analyze, brainstorm, search, document, or help.",
"assistant.slashCommands[].icon must be one of FileText, Languages, Globe, or HelpCircle.",
"assistant.suggestionGroups[].options[].flowId should match a key in assistant.demoFlows.",
"assistant.demoFlows.*.steps[].toolId must match an id in assistant.tools.",
"Configured tools render with the generic renderer unless source code is changed to add a specialized renderer.",
],
"webpage-assistant": [
"hostUi.root.props.defaultPageId must be one of the ids in root.props.pages.",
"hostUi.root.props.navGroups[].pageIds must reference ids that exist in pages.",
"assistant.suggestedPrompts[].flowId must match a key in assistant.demoFlows.",
"assistant.demoFlows.*.steps[].toolId must match an id in assistant.tools.",
"Each demo flow step must include assistantText, toolId, input, and output.",
],
"product-page-assistant": [
"If hostUi is provided, provide the complete tree — hostUi is not deep-merged with defaults.",
"assistant.suggestedPrompts[].scenarioId must match a key in assistant.demoFlows and a pack id in assistant.toolData.scenarioPacks.",
"assistant.demoFlows.*.steps[].toolId must match an id in assistant.tools.",
"Each demo flow step must include assistantText, toolId, input, and output.",
"demoFlows step input and output must match the tool's input shape and outputShape respectively.",
],
};