+ {block.label} +
+ {/* + Shiki emits a completethat already carries its own background, + padding, and `overflow-x: auto`, so this wrapper owns only the frame. + `overflow: hidden` is what makes the radius clip that background — it + must not be `auto`, which would nest a second scroll container around + a element that already scrolls and can show two scrollbars. + */} + +
| {{ row.at | date: 'medium' }} | +{{ row.action.description }} | +{{ row.decision.approved ? 'Approved' : 'Rejected' }} | +{{ row.decision.reason }} | +
{{ checkpoints().length }} checkpoints on this thread.
`, + }, + ], ctaHeadline: 'Ship compliant AI agents — without the compliance tax', ctaSubtext: 'Download the field report or start a pilot. Your compliance team will thank you.', metaTitle: 'Compliance & Audit — Threadplane Solutions', @@ -150,6 +222,35 @@ export const SOLUTIONS: SolutionConfig[] = [ { metric: 'Streaming', label: 'Token-level updates as the agent reasons over your data — first results visible before completion' }, { metric: 'Inline', label: 'Charts, tables, and KPI cards rendered into the conversation as Angular components you already own' }, ], + code: [ + { + label: 'dashboard.component.ts — the view catalog', + language: 'typescript', + source: `import { ChatComponent, views } from '@threadplane/chat'; +import { injectAgent } from '@threadplane/langgraph'; + +// Your components, keyed by the name the agent uses in its spec. +// Nothing here knows what question the user will ask. +const analyticsViews = views({ + bar_chart: BarChartComponent, + data_table: DataTableComponent, + kpi_card: KpiCardComponent, +}); + +export class DashboardComponent { + protected readonly agent = injectAgent(); + protected readonly analyticsViews = analyticsViews; +}`, + }, + { + label: 'dashboard.component.html', + language: 'html', + source: ` +