// Agent card document — ported from AgentCardDocument.tsx import { Document, Page, View, Text } from '@react-pdf/renderer'; import { AgentCardCover } from './cover.js'; import { styles, colors } from '../styles.js'; import { getScoreHexColor } from '../scoring.js'; import type { AgentCardData, AgentCardTool, AgentCardKnowledgeBase, AgentCardLLMConfig, AgentCardEvalRun, LifecycleStage, V1Owner, ComponentScoreDetail, } from './types.js'; interface AgentCardDocumentProps { data: AgentCardData; } // --------------------------------------------------------------------------- // Shared helpers // --------------------------------------------------------------------------- function PageHeader({ title, pageNumber }: { title: string; pageNumber: number }) { return ( {title} Page {pageNumber} ); } function PageFooter({ generatedDate }: { generatedDate: string }) { return ( Generated {generatedDate} Indemn Agent Card ); } function ComponentScoreBadge({ label, detail }: { label: string; detail?: ComponentScoreDetail }) { if (!detail || detail.total === 0) return null; const rate = detail.passed / detail.total; const pct = Math.round(rate * 100); return ( {label}: {pct}% ({detail.passed}/{detail.total}) ); } // --------------------------------------------------------------------------- // Page 2: System Prompt // --------------------------------------------------------------------------- function SystemPromptPage({ systemPrompt, generatedDate, componentScore, }: { systemPrompt?: string; generatedDate: string; componentScore?: ComponentScoreDetail; }) { return ( System Prompt Page 2 {systemPrompt ? ( {systemPrompt} ) : ( No system prompt configured )} ); } // --------------------------------------------------------------------------- // Page 3: Tools // --------------------------------------------------------------------------- function ToolsPage({ tools, generatedDate, componentScore, }: { tools: AgentCardTool[]; generatedDate: string; componentScore?: ComponentScoreDetail; }) { return ( Tools ({tools.length}) Page 3 {tools.length > 0 ? ( {tools.map((tool) => ( {tool.name} {tool.tool_name} {tool.description && ( {tool.description} )} {tool.type} ))} ) : ( No tools configured )} ); } // --------------------------------------------------------------------------- // Page 4: Knowledge Bases // --------------------------------------------------------------------------- function KnowledgeBasesPage({ knowledgeBases, generatedDate, componentScore, }: { knowledgeBases: AgentCardKnowledgeBase[]; generatedDate: string; componentScore?: ComponentScoreDetail; }) { return ( Knowledge Bases ({knowledgeBases.length}) Page 4 {knowledgeBases.length > 0 ? ( {knowledgeBases.map((kb) => ( {kb.name} {kb.type} {kb.document_count} documents ))} ) : ( No knowledge bases linked )} ); } // --------------------------------------------------------------------------- // Page 5: LLM Configuration // --------------------------------------------------------------------------- function LLMConfigPage({ llmConfig, generatedDate, }: { llmConfig?: AgentCardLLMConfig; generatedDate: string; }) { return ( {llmConfig ? ( Provider {llmConfig.provider || 'N/A'} Model {llmConfig.model || 'N/A'} {llmConfig.parameters && Object.keys(llmConfig.parameters).length > 0 && ( Parameters {Object.entries(llmConfig.parameters).map(([key, value]) => ( {key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())} {String(value)} ))} )} ) : ( No LLM configuration set (using defaults) )} ); } // --------------------------------------------------------------------------- // Page 6: Evaluation History // --------------------------------------------------------------------------- function EvaluationHistoryPage({ runs, generatedDate, }: { runs: AgentCardEvalRun[]; generatedDate: string; }) { const completedRuns = runs.filter(r => r.status === 'completed'); const recentRuns = completedRuns.slice(0, 10); return ( {recentRuns.length > 0 ? ( {/* Table header */} Date Model Items Criteria Rubric {/* Table rows */} {recentRuns.map((run, i) => { const date = run.completed_at || run.created_at; const dateStr = new Date(date).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); const model = run.bot_llm_model || 'N/A'; const criteriaStr = run.criteriaScore !== null ? `${run.criteriaScore}% (${run.criteriaPassed}/${run.criteriaTotal})` : '-'; const rubricStr = run.rubricScore !== null ? `${run.rubricScore}% (${run.rubricRulesPassed}/${run.rubricRulesTotal})` : '-'; return ( {dateStr} {model} {run.completed}/{run.total} {criteriaStr} {rubricStr} ); })} ) : ( No completed evaluation runs )} ); } // --------------------------------------------------------------------------- // Page 7: Metadata // --------------------------------------------------------------------------- function MetadataPage({ botId, organizationId, lifecycle, owner, generatedDate, }: { botId: string; organizationId?: string; lifecycle?: LifecycleStage; owner?: V1Owner; generatedDate: string; }) { const ownerName = owner ? [owner.firstname, owner.lastname].filter(Boolean).join(' ') || owner.email || 'Unknown' : undefined; const lcColors: Record = { prototype: { bg: '#e5e7eb', text: '#4b5563' }, beta: { bg: '#fef3c7', text: '#92400e' }, published: { bg: '#d1fae5', text: '#065f46' }, }; const lc = lifecycle ? lcColors[lifecycle] || lcColors.prototype : null; return ( {/* Row 1: Lifecycle + Owner */} Lifecycle Stage {lc ? ( {lifecycle!.charAt(0).toUpperCase() + lifecycle!.slice(1)} ) : ( Not set )} Owner {ownerName || 'Unassigned'} {owner?.email && ownerName !== owner.email && ( {owner.email} )} {/* Row 2: Bot ID + Org ID */} Bot ID {botId} Organization ID {organizationId || 'N/A'} {/* Row 3: Generated date */} Report Generated {generatedDate} ); } // --------------------------------------------------------------------------- // Document // --------------------------------------------------------------------------- export function AgentCardDocument({ data }: AgentCardDocumentProps) { const hasEvalRuns = data.evaluationRuns && data.evaluationRuns.length > 0; return ( {/* Page 1: Cover */} {/* Page 2: System Prompt */} {/* Page 3: Tools */} {/* Page 4: Knowledge Bases */} {/* Page 5: LLM Configuration */} {/* Page 6: Evaluation History (only if runs exist) */} {hasEvalRuns && ( )} {/* Page 7 (or 6 if no eval history): Metadata */} ); }