@indemn/cli 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +28 -0
- package/README.md +29 -23
- package/dist/cli/agents.d.ts.map +1 -1
- package/dist/cli/agents.js +20 -0
- package/dist/cli/agents.js.map +1 -1
- package/dist/cli/eval.d.ts.map +1 -1
- package/dist/cli/eval.js +38 -0
- package/dist/cli/eval.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +40 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/report/agent-card/cover.d.ts +20 -0
- package/dist/report/agent-card/cover.d.ts.map +1 -0
- package/dist/report/agent-card/cover.js +58 -0
- package/dist/report/agent-card/cover.js.map +1 -0
- package/dist/report/agent-card/document.d.ts +7 -0
- package/dist/report/agent-card/document.d.ts.map +1 -0
- package/dist/report/agent-card/document.js +144 -0
- package/dist/report/agent-card/document.js.map +1 -0
- package/dist/report/agent-card/types.d.ts +77 -0
- package/dist/report/agent-card/types.d.ts.map +1 -0
- package/dist/report/agent-card/types.js +3 -0
- package/dist/report/agent-card/types.js.map +1 -0
- package/dist/report/assets/Indemn_PrimaryLogo_Iris.png +0 -0
- package/dist/report/assets/assets/Indemn_PrimaryLogo_Iris.png +0 -0
- package/dist/report/assets/assets/fonts/Barlow-Bold.ttf +0 -0
- package/dist/report/assets/assets/fonts/Barlow-Medium.ttf +0 -0
- package/dist/report/assets/assets/fonts/Barlow-Regular.ttf +0 -0
- package/dist/report/assets/assets/fonts/Barlow-SemiBold.ttf +0 -0
- package/dist/report/assets/fonts/Barlow-Bold.ttf +0 -0
- package/dist/report/assets/fonts/Barlow-Medium.ttf +0 -0
- package/dist/report/assets/fonts/Barlow-Regular.ttf +0 -0
- package/dist/report/assets/fonts/Barlow-SemiBold.ttf +0 -0
- package/dist/report/eval-report/cover.d.ts +16 -0
- package/dist/report/eval-report/cover.d.ts.map +1 -0
- package/dist/report/eval-report/cover.js +8 -0
- package/dist/report/eval-report/cover.js.map +1 -0
- package/dist/report/eval-report/document.d.ts +19 -0
- package/dist/report/eval-report/document.d.ts.map +1 -0
- package/dist/report/eval-report/document.js +32 -0
- package/dist/report/eval-report/document.js.map +1 -0
- package/dist/report/eval-report/example-page.d.ts +11 -0
- package/dist/report/eval-report/example-page.d.ts.map +1 -0
- package/dist/report/eval-report/example-page.js +18 -0
- package/dist/report/eval-report/example-page.js.map +1 -0
- package/dist/report/eval-report/item-page.d.ts +9 -0
- package/dist/report/eval-report/item-page.d.ts.map +1 -0
- package/dist/report/eval-report/item-page.js +72 -0
- package/dist/report/eval-report/item-page.js.map +1 -0
- package/dist/report/eval-report/matrix-page.d.ts +8 -0
- package/dist/report/eval-report/matrix-page.d.ts.map +1 -0
- package/dist/report/eval-report/matrix-page.js +31 -0
- package/dist/report/eval-report/matrix-page.js.map +1 -0
- package/dist/report/eval-report/types.d.ts +69 -0
- package/dist/report/eval-report/types.d.ts.map +1 -0
- package/dist/report/eval-report/types.js +7 -0
- package/dist/report/eval-report/types.js.map +1 -0
- package/dist/report/eval-report/v2-cover.d.ts +9 -0
- package/dist/report/eval-report/v2-cover.d.ts.map +1 -0
- package/dist/report/eval-report/v2-cover.js +32 -0
- package/dist/report/eval-report/v2-cover.js.map +1 -0
- package/dist/report/export.d.ts +17 -0
- package/dist/report/export.d.ts.map +1 -0
- package/dist/report/export.js +327 -0
- package/dist/report/export.js.map +1 -0
- package/dist/report/generate.d.ts +7 -0
- package/dist/report/generate.d.ts.map +1 -0
- package/dist/report/generate.js +30 -0
- package/dist/report/generate.js.map +1 -0
- package/dist/report/scoring.d.ts +90 -0
- package/dist/report/scoring.d.ts.map +1 -0
- package/dist/report/scoring.js +174 -0
- package/dist/report/scoring.js.map +1 -0
- package/dist/report/styles.d.ts +111 -0
- package/dist/report/styles.d.ts.map +1 -0
- package/dist/report/styles.js +134 -0
- package/dist/report/styles.js.map +1 -0
- package/docs/plans/2026-03-13-cli-exports.md +819 -0
- package/package.json +14 -4
- package/skills/eval-analysis/SKILL.md +178 -0
- package/skills/eval-analysis/references/data-shapes.md +279 -0
- package/src/cli/agents.ts +22 -0
- package/src/cli/eval.ts +42 -0
- package/src/mcp/tools.ts +50 -0
- package/src/report/agent-card/cover.tsx +232 -0
- package/src/report/agent-card/document.tsx +582 -0
- package/src/report/agent-card/types.ts +86 -0
- package/src/report/assets/Indemn_PrimaryLogo_Iris.png +0 -0
- package/src/report/assets/fonts/Barlow-Bold.ttf +0 -0
- package/src/report/assets/fonts/Barlow-Medium.ttf +0 -0
- package/src/report/assets/fonts/Barlow-Regular.ttf +0 -0
- package/src/report/assets/fonts/Barlow-SemiBold.ttf +0 -0
- package/src/report/eval-report/cover.tsx +69 -0
- package/src/report/eval-report/document.tsx +105 -0
- package/src/report/eval-report/example-page.tsx +121 -0
- package/src/report/eval-report/item-page.tsx +211 -0
- package/src/report/eval-report/matrix-page.tsx +124 -0
- package/src/report/eval-report/types.ts +77 -0
- package/src/report/eval-report/v2-cover.tsx +102 -0
- package/src/report/export.ts +394 -0
- package/src/report/generate.tsx +37 -0
- package/src/report/scoring.ts +281 -0
- package/src/report/styles.ts +138 -0
- package/tsconfig.json +2 -1
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
// Agent card document — ported from AgentCardDocument.tsx
|
|
2
|
+
import { Document, Page, View, Text } from '@react-pdf/renderer';
|
|
3
|
+
import { AgentCardCover } from './cover.js';
|
|
4
|
+
import { styles, colors } from '../styles.js';
|
|
5
|
+
import { getScoreHexColor } from '../scoring.js';
|
|
6
|
+
import type {
|
|
7
|
+
AgentCardData,
|
|
8
|
+
AgentCardTool,
|
|
9
|
+
AgentCardKnowledgeBase,
|
|
10
|
+
AgentCardLLMConfig,
|
|
11
|
+
AgentCardEvalRun,
|
|
12
|
+
LifecycleStage,
|
|
13
|
+
V1Owner,
|
|
14
|
+
ComponentScoreDetail,
|
|
15
|
+
} from './types.js';
|
|
16
|
+
|
|
17
|
+
interface AgentCardDocumentProps {
|
|
18
|
+
data: AgentCardData;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Shared helpers
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
function PageHeader({ title, pageNumber }: { title: string; pageNumber: number }) {
|
|
26
|
+
return (
|
|
27
|
+
<View style={styles.pageHeader}>
|
|
28
|
+
<Text style={styles.pageTitle}>{title}</Text>
|
|
29
|
+
<Text style={styles.pageNumber}>Page {pageNumber}</Text>
|
|
30
|
+
</View>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function PageFooter({ generatedDate }: { generatedDate: string }) {
|
|
35
|
+
return (
|
|
36
|
+
<View style={styles.footer}>
|
|
37
|
+
<Text style={styles.caption}>Generated {generatedDate}</Text>
|
|
38
|
+
<Text style={styles.caption}>Indemn Agent Card</Text>
|
|
39
|
+
</View>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function ComponentScoreBadge({ label, detail }: { label: string; detail?: ComponentScoreDetail }) {
|
|
44
|
+
if (!detail || detail.total === 0) return null;
|
|
45
|
+
const rate = detail.passed / detail.total;
|
|
46
|
+
const pct = Math.round(rate * 100);
|
|
47
|
+
return (
|
|
48
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
49
|
+
<View
|
|
50
|
+
style={{
|
|
51
|
+
backgroundColor: `${getScoreHexColor(rate)}18`,
|
|
52
|
+
paddingHorizontal: 8,
|
|
53
|
+
paddingVertical: 3,
|
|
54
|
+
borderRadius: 4,
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
<Text style={{ fontSize: 9, fontWeight: 600, color: getScoreHexColor(rate) }}>
|
|
58
|
+
{label}: {pct}% ({detail.passed}/{detail.total})
|
|
59
|
+
</Text>
|
|
60
|
+
</View>
|
|
61
|
+
</View>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Page 2: System Prompt
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
function SystemPromptPage({
|
|
70
|
+
systemPrompt,
|
|
71
|
+
generatedDate,
|
|
72
|
+
componentScore,
|
|
73
|
+
}: {
|
|
74
|
+
systemPrompt?: string;
|
|
75
|
+
generatedDate: string;
|
|
76
|
+
componentScore?: ComponentScoreDetail;
|
|
77
|
+
}) {
|
|
78
|
+
return (
|
|
79
|
+
<Page size="A4" style={styles.page}>
|
|
80
|
+
<View style={styles.pageHeader}>
|
|
81
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>
|
|
82
|
+
<Text style={styles.pageTitle}>System Prompt</Text>
|
|
83
|
+
<ComponentScoreBadge label="Prompt Score" detail={componentScore} />
|
|
84
|
+
</View>
|
|
85
|
+
<Text style={styles.pageNumber}>Page 2</Text>
|
|
86
|
+
</View>
|
|
87
|
+
|
|
88
|
+
{systemPrompt ? (
|
|
89
|
+
<View
|
|
90
|
+
style={{
|
|
91
|
+
backgroundColor: colors.background,
|
|
92
|
+
borderRadius: 6,
|
|
93
|
+
padding: 16,
|
|
94
|
+
flex: 1,
|
|
95
|
+
marginBottom: 60,
|
|
96
|
+
}}
|
|
97
|
+
>
|
|
98
|
+
<Text
|
|
99
|
+
style={{
|
|
100
|
+
fontFamily: 'Courier',
|
|
101
|
+
fontSize: 9,
|
|
102
|
+
lineHeight: 1.6,
|
|
103
|
+
color: colors.eggplant,
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
{systemPrompt}
|
|
107
|
+
</Text>
|
|
108
|
+
</View>
|
|
109
|
+
) : (
|
|
110
|
+
<View style={[styles.card, { alignItems: 'center', paddingVertical: 40 }]}>
|
|
111
|
+
<Text style={{ fontSize: 12, color: colors.muted }}>
|
|
112
|
+
No system prompt configured
|
|
113
|
+
</Text>
|
|
114
|
+
</View>
|
|
115
|
+
)}
|
|
116
|
+
|
|
117
|
+
<PageFooter generatedDate={generatedDate} />
|
|
118
|
+
</Page>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// Page 3: Tools
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
|
|
126
|
+
function ToolsPage({
|
|
127
|
+
tools,
|
|
128
|
+
generatedDate,
|
|
129
|
+
componentScore,
|
|
130
|
+
}: {
|
|
131
|
+
tools: AgentCardTool[];
|
|
132
|
+
generatedDate: string;
|
|
133
|
+
componentScore?: ComponentScoreDetail;
|
|
134
|
+
}) {
|
|
135
|
+
return (
|
|
136
|
+
<Page size="A4" style={styles.page}>
|
|
137
|
+
<View style={styles.pageHeader}>
|
|
138
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>
|
|
139
|
+
<Text style={styles.pageTitle}>Tools ({tools.length})</Text>
|
|
140
|
+
<ComponentScoreBadge label="Function Score" detail={componentScore} />
|
|
141
|
+
</View>
|
|
142
|
+
<Text style={styles.pageNumber}>Page 3</Text>
|
|
143
|
+
</View>
|
|
144
|
+
|
|
145
|
+
{tools.length > 0 ? (
|
|
146
|
+
<View
|
|
147
|
+
style={{
|
|
148
|
+
flexDirection: 'row',
|
|
149
|
+
flexWrap: 'wrap',
|
|
150
|
+
gap: 12,
|
|
151
|
+
marginBottom: 60,
|
|
152
|
+
}}
|
|
153
|
+
>
|
|
154
|
+
{tools.map((tool) => (
|
|
155
|
+
<View
|
|
156
|
+
key={tool.id}
|
|
157
|
+
style={{
|
|
158
|
+
width: '48%',
|
|
159
|
+
backgroundColor: colors.background,
|
|
160
|
+
borderRadius: 6,
|
|
161
|
+
padding: 12,
|
|
162
|
+
}}
|
|
163
|
+
>
|
|
164
|
+
<Text style={{ fontSize: 11, fontWeight: 600, color: colors.eggplant, marginBottom: 4 }}>
|
|
165
|
+
{tool.name}
|
|
166
|
+
</Text>
|
|
167
|
+
<Text style={{ fontSize: 9, fontFamily: 'Courier', color: colors.muted, marginBottom: 4 }}>
|
|
168
|
+
{tool.tool_name}
|
|
169
|
+
</Text>
|
|
170
|
+
{tool.description && (
|
|
171
|
+
<Text style={{ fontSize: 9, color: colors.muted, lineHeight: 1.4, marginBottom: 4 }}>
|
|
172
|
+
{tool.description}
|
|
173
|
+
</Text>
|
|
174
|
+
)}
|
|
175
|
+
<View
|
|
176
|
+
style={{
|
|
177
|
+
backgroundColor: colors.white,
|
|
178
|
+
paddingHorizontal: 6,
|
|
179
|
+
paddingVertical: 2,
|
|
180
|
+
borderRadius: 3,
|
|
181
|
+
alignSelf: 'flex-start',
|
|
182
|
+
}}
|
|
183
|
+
>
|
|
184
|
+
<Text style={{ fontSize: 8, fontWeight: 500, color: colors.iris }}>
|
|
185
|
+
{tool.type}
|
|
186
|
+
</Text>
|
|
187
|
+
</View>
|
|
188
|
+
</View>
|
|
189
|
+
))}
|
|
190
|
+
</View>
|
|
191
|
+
) : (
|
|
192
|
+
<View style={[styles.card, { alignItems: 'center', paddingVertical: 40 }]}>
|
|
193
|
+
<Text style={{ fontSize: 12, color: colors.muted }}>
|
|
194
|
+
No tools configured
|
|
195
|
+
</Text>
|
|
196
|
+
</View>
|
|
197
|
+
)}
|
|
198
|
+
|
|
199
|
+
<PageFooter generatedDate={generatedDate} />
|
|
200
|
+
</Page>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// Page 4: Knowledge Bases
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
|
|
208
|
+
function KnowledgeBasesPage({
|
|
209
|
+
knowledgeBases,
|
|
210
|
+
generatedDate,
|
|
211
|
+
componentScore,
|
|
212
|
+
}: {
|
|
213
|
+
knowledgeBases: AgentCardKnowledgeBase[];
|
|
214
|
+
generatedDate: string;
|
|
215
|
+
componentScore?: ComponentScoreDetail;
|
|
216
|
+
}) {
|
|
217
|
+
return (
|
|
218
|
+
<Page size="A4" style={styles.page}>
|
|
219
|
+
<View style={styles.pageHeader}>
|
|
220
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>
|
|
221
|
+
<Text style={styles.pageTitle}>Knowledge Bases ({knowledgeBases.length})</Text>
|
|
222
|
+
<ComponentScoreBadge label="KB Score" detail={componentScore} />
|
|
223
|
+
</View>
|
|
224
|
+
<Text style={styles.pageNumber}>Page 4</Text>
|
|
225
|
+
</View>
|
|
226
|
+
|
|
227
|
+
{knowledgeBases.length > 0 ? (
|
|
228
|
+
<View
|
|
229
|
+
style={{
|
|
230
|
+
flexDirection: 'row',
|
|
231
|
+
flexWrap: 'wrap',
|
|
232
|
+
gap: 12,
|
|
233
|
+
marginBottom: 60,
|
|
234
|
+
}}
|
|
235
|
+
>
|
|
236
|
+
{knowledgeBases.map((kb) => (
|
|
237
|
+
<View
|
|
238
|
+
key={kb.id}
|
|
239
|
+
style={{
|
|
240
|
+
width: '48%',
|
|
241
|
+
backgroundColor: colors.background,
|
|
242
|
+
borderRadius: 6,
|
|
243
|
+
padding: 12,
|
|
244
|
+
}}
|
|
245
|
+
>
|
|
246
|
+
<Text style={{ fontSize: 11, fontWeight: 600, color: colors.eggplant, marginBottom: 4 }}>
|
|
247
|
+
{kb.name}
|
|
248
|
+
</Text>
|
|
249
|
+
<View style={{ flexDirection: 'row', gap: 8, alignItems: 'center' }}>
|
|
250
|
+
<View
|
|
251
|
+
style={{
|
|
252
|
+
backgroundColor: colors.white,
|
|
253
|
+
paddingHorizontal: 6,
|
|
254
|
+
paddingVertical: 2,
|
|
255
|
+
borderRadius: 3,
|
|
256
|
+
}}
|
|
257
|
+
>
|
|
258
|
+
<Text style={{ fontSize: 8, fontWeight: 500, color: colors.iris }}>
|
|
259
|
+
{kb.type}
|
|
260
|
+
</Text>
|
|
261
|
+
</View>
|
|
262
|
+
<Text style={{ fontSize: 9, color: colors.muted }}>
|
|
263
|
+
{kb.document_count} documents
|
|
264
|
+
</Text>
|
|
265
|
+
</View>
|
|
266
|
+
</View>
|
|
267
|
+
))}
|
|
268
|
+
</View>
|
|
269
|
+
) : (
|
|
270
|
+
<View style={[styles.card, { alignItems: 'center', paddingVertical: 40 }]}>
|
|
271
|
+
<Text style={{ fontSize: 12, color: colors.muted }}>
|
|
272
|
+
No knowledge bases linked
|
|
273
|
+
</Text>
|
|
274
|
+
</View>
|
|
275
|
+
)}
|
|
276
|
+
|
|
277
|
+
<PageFooter generatedDate={generatedDate} />
|
|
278
|
+
</Page>
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
// Page 5: LLM Configuration
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
|
|
286
|
+
function LLMConfigPage({
|
|
287
|
+
llmConfig,
|
|
288
|
+
generatedDate,
|
|
289
|
+
}: {
|
|
290
|
+
llmConfig?: AgentCardLLMConfig;
|
|
291
|
+
generatedDate: string;
|
|
292
|
+
}) {
|
|
293
|
+
return (
|
|
294
|
+
<Page size="A4" style={styles.page}>
|
|
295
|
+
<PageHeader title="LLM Configuration" pageNumber={5} />
|
|
296
|
+
|
|
297
|
+
{llmConfig ? (
|
|
298
|
+
<View style={[styles.card, { marginBottom: 60 }]}>
|
|
299
|
+
<View style={{ flexDirection: 'row', marginBottom: 12 }}>
|
|
300
|
+
<View style={{ flex: 1 }}>
|
|
301
|
+
<Text style={{ fontSize: 10, color: colors.muted, marginBottom: 4 }}>Provider</Text>
|
|
302
|
+
<Text style={{ fontSize: 12, fontWeight: 500, color: colors.eggplant }}>
|
|
303
|
+
{llmConfig.provider || 'N/A'}
|
|
304
|
+
</Text>
|
|
305
|
+
</View>
|
|
306
|
+
<View style={{ flex: 1 }}>
|
|
307
|
+
<Text style={{ fontSize: 10, color: colors.muted, marginBottom: 4 }}>Model</Text>
|
|
308
|
+
<Text style={{ fontSize: 12, fontWeight: 500, fontFamily: 'Courier', color: colors.eggplant }}>
|
|
309
|
+
{llmConfig.model || 'N/A'}
|
|
310
|
+
</Text>
|
|
311
|
+
</View>
|
|
312
|
+
</View>
|
|
313
|
+
|
|
314
|
+
{llmConfig.parameters && Object.keys(llmConfig.parameters).length > 0 && (
|
|
315
|
+
<View>
|
|
316
|
+
<Text style={{ fontSize: 10, color: colors.muted, marginBottom: 8 }}>Parameters</Text>
|
|
317
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 12 }}>
|
|
318
|
+
{Object.entries(llmConfig.parameters).map(([key, value]) => (
|
|
319
|
+
<View key={key} style={{ backgroundColor: colors.white, borderRadius: 4, padding: 8, minWidth: 100 }}>
|
|
320
|
+
<Text style={{ fontSize: 9, color: colors.muted, marginBottom: 2 }}>
|
|
321
|
+
{key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())}
|
|
322
|
+
</Text>
|
|
323
|
+
<Text style={{ fontSize: 11, fontFamily: 'Courier', color: colors.eggplant }}>
|
|
324
|
+
{String(value)}
|
|
325
|
+
</Text>
|
|
326
|
+
</View>
|
|
327
|
+
))}
|
|
328
|
+
</View>
|
|
329
|
+
</View>
|
|
330
|
+
)}
|
|
331
|
+
</View>
|
|
332
|
+
) : (
|
|
333
|
+
<View style={[styles.card, { alignItems: 'center', paddingVertical: 40 }]}>
|
|
334
|
+
<Text style={{ fontSize: 12, color: colors.muted }}>
|
|
335
|
+
No LLM configuration set (using defaults)
|
|
336
|
+
</Text>
|
|
337
|
+
</View>
|
|
338
|
+
)}
|
|
339
|
+
|
|
340
|
+
<PageFooter generatedDate={generatedDate} />
|
|
341
|
+
</Page>
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
// Page 6: Evaluation History
|
|
347
|
+
// ---------------------------------------------------------------------------
|
|
348
|
+
|
|
349
|
+
function EvaluationHistoryPage({
|
|
350
|
+
runs,
|
|
351
|
+
generatedDate,
|
|
352
|
+
}: {
|
|
353
|
+
runs: AgentCardEvalRun[];
|
|
354
|
+
generatedDate: string;
|
|
355
|
+
}) {
|
|
356
|
+
const completedRuns = runs.filter(r => r.status === 'completed');
|
|
357
|
+
const recentRuns = completedRuns.slice(0, 10);
|
|
358
|
+
|
|
359
|
+
return (
|
|
360
|
+
<Page size="A4" style={styles.page}>
|
|
361
|
+
<PageHeader title={`Evaluation History (${completedRuns.length} runs)`} pageNumber={6} />
|
|
362
|
+
|
|
363
|
+
{recentRuns.length > 0 ? (
|
|
364
|
+
<View style={{ marginBottom: 60 }}>
|
|
365
|
+
{/* Table header */}
|
|
366
|
+
<View
|
|
367
|
+
style={{
|
|
368
|
+
flexDirection: 'row',
|
|
369
|
+
backgroundColor: colors.eggplant,
|
|
370
|
+
borderTopLeftRadius: 6,
|
|
371
|
+
borderTopRightRadius: 6,
|
|
372
|
+
paddingVertical: 8,
|
|
373
|
+
paddingHorizontal: 12,
|
|
374
|
+
}}
|
|
375
|
+
>
|
|
376
|
+
<Text style={{ flex: 2, fontSize: 9, fontWeight: 600, color: colors.white }}>Date</Text>
|
|
377
|
+
<Text style={{ flex: 2, fontSize: 9, fontWeight: 600, color: colors.white }}>Model</Text>
|
|
378
|
+
<Text style={{ flex: 1, fontSize: 9, fontWeight: 600, color: colors.white, textAlign: 'center' }}>Items</Text>
|
|
379
|
+
<Text style={{ flex: 1.5, fontSize: 9, fontWeight: 600, color: colors.white, textAlign: 'center' }}>Criteria</Text>
|
|
380
|
+
<Text style={{ flex: 1.5, fontSize: 9, fontWeight: 600, color: colors.white, textAlign: 'center' }}>Rubric</Text>
|
|
381
|
+
</View>
|
|
382
|
+
|
|
383
|
+
{/* Table rows */}
|
|
384
|
+
{recentRuns.map((run, i) => {
|
|
385
|
+
const date = run.completed_at || run.created_at;
|
|
386
|
+
const dateStr = new Date(date).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
|
|
387
|
+
const model = run.bot_llm_model || 'N/A';
|
|
388
|
+
const criteriaStr = run.criteriaScore !== null ? `${run.criteriaScore}% (${run.criteriaPassed}/${run.criteriaTotal})` : '-';
|
|
389
|
+
const rubricStr = run.rubricScore !== null ? `${run.rubricScore}% (${run.rubricRulesPassed}/${run.rubricRulesTotal})` : '-';
|
|
390
|
+
|
|
391
|
+
return (
|
|
392
|
+
<View
|
|
393
|
+
key={run.run_id}
|
|
394
|
+
style={{
|
|
395
|
+
flexDirection: 'row',
|
|
396
|
+
backgroundColor: i % 2 === 0 ? colors.background : colors.white,
|
|
397
|
+
paddingVertical: 7,
|
|
398
|
+
paddingHorizontal: 12,
|
|
399
|
+
...(i === recentRuns.length - 1 ? { borderBottomLeftRadius: 6, borderBottomRightRadius: 6 } : {}),
|
|
400
|
+
}}
|
|
401
|
+
>
|
|
402
|
+
<Text style={{ flex: 2, fontSize: 9, color: colors.eggplant }}>{dateStr}</Text>
|
|
403
|
+
<Text style={{ flex: 2, fontSize: 9, fontFamily: 'Courier', color: colors.eggplant }}>{model}</Text>
|
|
404
|
+
<Text style={{ flex: 1, fontSize: 9, color: colors.muted, textAlign: 'center' }}>{run.completed}/{run.total}</Text>
|
|
405
|
+
<Text style={{ flex: 1.5, fontSize: 9, fontWeight: 500, color: run.criteriaScore !== null ? getScoreHexColor(run.criteriaScore / 100) : colors.muted, textAlign: 'center' }}>
|
|
406
|
+
{criteriaStr}
|
|
407
|
+
</Text>
|
|
408
|
+
<Text style={{ flex: 1.5, fontSize: 9, fontWeight: 500, color: run.rubricScore !== null ? getScoreHexColor(run.rubricScore / 100) : colors.muted, textAlign: 'center' }}>
|
|
409
|
+
{rubricStr}
|
|
410
|
+
</Text>
|
|
411
|
+
</View>
|
|
412
|
+
);
|
|
413
|
+
})}
|
|
414
|
+
</View>
|
|
415
|
+
) : (
|
|
416
|
+
<View style={[styles.card, { alignItems: 'center', paddingVertical: 40 }]}>
|
|
417
|
+
<Text style={{ fontSize: 12, color: colors.muted }}>
|
|
418
|
+
No completed evaluation runs
|
|
419
|
+
</Text>
|
|
420
|
+
</View>
|
|
421
|
+
)}
|
|
422
|
+
|
|
423
|
+
<PageFooter generatedDate={generatedDate} />
|
|
424
|
+
</Page>
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// ---------------------------------------------------------------------------
|
|
429
|
+
// Page 7: Metadata
|
|
430
|
+
// ---------------------------------------------------------------------------
|
|
431
|
+
|
|
432
|
+
function MetadataPage({
|
|
433
|
+
botId,
|
|
434
|
+
organizationId,
|
|
435
|
+
lifecycle,
|
|
436
|
+
owner,
|
|
437
|
+
generatedDate,
|
|
438
|
+
}: {
|
|
439
|
+
botId: string;
|
|
440
|
+
organizationId?: string;
|
|
441
|
+
lifecycle?: LifecycleStage;
|
|
442
|
+
owner?: V1Owner;
|
|
443
|
+
generatedDate: string;
|
|
444
|
+
}) {
|
|
445
|
+
const ownerName = owner
|
|
446
|
+
? [owner.firstname, owner.lastname].filter(Boolean).join(' ') || owner.email || 'Unknown'
|
|
447
|
+
: undefined;
|
|
448
|
+
|
|
449
|
+
const lcColors: Record<string, { bg: string; text: string }> = {
|
|
450
|
+
prototype: { bg: '#e5e7eb', text: '#4b5563' },
|
|
451
|
+
beta: { bg: '#fef3c7', text: '#92400e' },
|
|
452
|
+
published: { bg: '#d1fae5', text: '#065f46' },
|
|
453
|
+
};
|
|
454
|
+
const lc = lifecycle ? lcColors[lifecycle] || lcColors.prototype : null;
|
|
455
|
+
|
|
456
|
+
return (
|
|
457
|
+
<Page size="A4" style={styles.page}>
|
|
458
|
+
<PageHeader title="Metadata" pageNumber={7} />
|
|
459
|
+
|
|
460
|
+
<View style={[styles.card, { marginBottom: 60 }]}>
|
|
461
|
+
{/* Row 1: Lifecycle + Owner */}
|
|
462
|
+
<View style={{ flexDirection: 'row', marginBottom: 16 }}>
|
|
463
|
+
<View style={{ flex: 1 }}>
|
|
464
|
+
<Text style={{ fontSize: 10, color: colors.muted, marginBottom: 4 }}>Lifecycle Stage</Text>
|
|
465
|
+
{lc ? (
|
|
466
|
+
<View style={{ backgroundColor: lc.bg, paddingHorizontal: 8, paddingVertical: 3, borderRadius: 4, alignSelf: 'flex-start' }}>
|
|
467
|
+
<Text style={{ fontSize: 10, fontWeight: 600, color: lc.text }}>
|
|
468
|
+
{lifecycle!.charAt(0).toUpperCase() + lifecycle!.slice(1)}
|
|
469
|
+
</Text>
|
|
470
|
+
</View>
|
|
471
|
+
) : (
|
|
472
|
+
<Text style={{ fontSize: 11, color: colors.muted }}>Not set</Text>
|
|
473
|
+
)}
|
|
474
|
+
</View>
|
|
475
|
+
<View style={{ flex: 1 }}>
|
|
476
|
+
<Text style={{ fontSize: 10, color: colors.muted, marginBottom: 4 }}>Owner</Text>
|
|
477
|
+
<Text style={{ fontSize: 11, color: colors.eggplant }}>
|
|
478
|
+
{ownerName || 'Unassigned'}
|
|
479
|
+
</Text>
|
|
480
|
+
{owner?.email && ownerName !== owner.email && (
|
|
481
|
+
<Text style={{ fontSize: 9, color: colors.muted }}>{owner.email}</Text>
|
|
482
|
+
)}
|
|
483
|
+
</View>
|
|
484
|
+
</View>
|
|
485
|
+
|
|
486
|
+
{/* Row 2: Bot ID + Org ID */}
|
|
487
|
+
<View style={{ flexDirection: 'row', marginBottom: 12 }}>
|
|
488
|
+
<View style={{ flex: 1 }}>
|
|
489
|
+
<Text style={{ fontSize: 10, color: colors.muted, marginBottom: 4 }}>Bot ID</Text>
|
|
490
|
+
<Text style={{ fontSize: 11, fontFamily: 'Courier', color: colors.eggplant }}>
|
|
491
|
+
{botId}
|
|
492
|
+
</Text>
|
|
493
|
+
</View>
|
|
494
|
+
<View style={{ flex: 1 }}>
|
|
495
|
+
<Text style={{ fontSize: 10, color: colors.muted, marginBottom: 4 }}>Organization ID</Text>
|
|
496
|
+
<Text style={{ fontSize: 11, fontFamily: 'Courier', color: colors.eggplant }}>
|
|
497
|
+
{organizationId || 'N/A'}
|
|
498
|
+
</Text>
|
|
499
|
+
</View>
|
|
500
|
+
</View>
|
|
501
|
+
|
|
502
|
+
{/* Row 3: Generated date */}
|
|
503
|
+
<View style={{ flexDirection: 'row' }}>
|
|
504
|
+
<View style={{ flex: 1 }}>
|
|
505
|
+
<Text style={{ fontSize: 10, color: colors.muted, marginBottom: 4 }}>Report Generated</Text>
|
|
506
|
+
<Text style={{ fontSize: 11, color: colors.eggplant }}>{generatedDate}</Text>
|
|
507
|
+
</View>
|
|
508
|
+
</View>
|
|
509
|
+
</View>
|
|
510
|
+
|
|
511
|
+
<PageFooter generatedDate={generatedDate} />
|
|
512
|
+
</Page>
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// ---------------------------------------------------------------------------
|
|
517
|
+
// Document
|
|
518
|
+
// ---------------------------------------------------------------------------
|
|
519
|
+
|
|
520
|
+
export function AgentCardDocument({ data }: AgentCardDocumentProps) {
|
|
521
|
+
const hasEvalRuns = data.evaluationRuns && data.evaluationRuns.length > 0;
|
|
522
|
+
|
|
523
|
+
return (
|
|
524
|
+
<Document
|
|
525
|
+
title={`Indemn Agent Card - ${data.name}`}
|
|
526
|
+
author="Indemn Platform"
|
|
527
|
+
subject={`Agent card for ${data.name}`}
|
|
528
|
+
>
|
|
529
|
+
{/* Page 1: Cover */}
|
|
530
|
+
<AgentCardCover
|
|
531
|
+
agentName={data.name}
|
|
532
|
+
description={data.description}
|
|
533
|
+
channels={data.channels}
|
|
534
|
+
generatedDate={data.generatedDate}
|
|
535
|
+
lifecycle={data.lifecycle}
|
|
536
|
+
owner={data.owner}
|
|
537
|
+
evaluationSummary={data.evaluationSummary}
|
|
538
|
+
/>
|
|
539
|
+
|
|
540
|
+
{/* Page 2: System Prompt */}
|
|
541
|
+
<SystemPromptPage
|
|
542
|
+
systemPrompt={data.system_prompt}
|
|
543
|
+
generatedDate={data.generatedDate}
|
|
544
|
+
componentScore={data.componentScores?.prompt}
|
|
545
|
+
/>
|
|
546
|
+
|
|
547
|
+
{/* Page 3: Tools */}
|
|
548
|
+
<ToolsPage
|
|
549
|
+
tools={data.tools}
|
|
550
|
+
generatedDate={data.generatedDate}
|
|
551
|
+
componentScore={data.componentScores?.function}
|
|
552
|
+
/>
|
|
553
|
+
|
|
554
|
+
{/* Page 4: Knowledge Bases */}
|
|
555
|
+
<KnowledgeBasesPage
|
|
556
|
+
knowledgeBases={data.knowledge_bases}
|
|
557
|
+
generatedDate={data.generatedDate}
|
|
558
|
+
componentScore={data.componentScores?.knowledge_base}
|
|
559
|
+
/>
|
|
560
|
+
|
|
561
|
+
{/* Page 5: LLM Configuration */}
|
|
562
|
+
<LLMConfigPage llmConfig={data.llm_config} generatedDate={data.generatedDate} />
|
|
563
|
+
|
|
564
|
+
{/* Page 6: Evaluation History (only if runs exist) */}
|
|
565
|
+
{hasEvalRuns && (
|
|
566
|
+
<EvaluationHistoryPage
|
|
567
|
+
runs={data.evaluationRuns!}
|
|
568
|
+
generatedDate={data.generatedDate}
|
|
569
|
+
/>
|
|
570
|
+
)}
|
|
571
|
+
|
|
572
|
+
{/* Page 7 (or 6 if no eval history): Metadata */}
|
|
573
|
+
<MetadataPage
|
|
574
|
+
botId={data.id}
|
|
575
|
+
organizationId={data.organization_id}
|
|
576
|
+
lifecycle={data.lifecycle}
|
|
577
|
+
owner={data.owner}
|
|
578
|
+
generatedDate={data.generatedDate}
|
|
579
|
+
/>
|
|
580
|
+
</Document>
|
|
581
|
+
);
|
|
582
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Agent card data types
|
|
2
|
+
|
|
3
|
+
export type LifecycleStage = 'prototype' | 'beta' | 'published';
|
|
4
|
+
|
|
5
|
+
export interface V1Owner {
|
|
6
|
+
firstname?: string;
|
|
7
|
+
lastname?: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ComponentScoreDetail {
|
|
12
|
+
score?: number;
|
|
13
|
+
total: number;
|
|
14
|
+
passed: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ComponentScores {
|
|
18
|
+
prompt?: ComponentScoreDetail;
|
|
19
|
+
knowledge_base?: ComponentScoreDetail;
|
|
20
|
+
function?: ComponentScoreDetail;
|
|
21
|
+
general?: ComponentScoreDetail;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AgentCardTool {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
tool_name: string;
|
|
28
|
+
type: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface AgentCardKnowledgeBase {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
type: string;
|
|
36
|
+
document_count: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface AgentCardLLMConfig {
|
|
40
|
+
provider?: string;
|
|
41
|
+
model?: string;
|
|
42
|
+
parameters?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface AgentCardEvalRun {
|
|
46
|
+
run_id: string;
|
|
47
|
+
status: string;
|
|
48
|
+
created_at: string;
|
|
49
|
+
completed_at?: string;
|
|
50
|
+
bot_llm_model?: string;
|
|
51
|
+
bot_llm_provider?: string;
|
|
52
|
+
criteriaScore: number | null; // 0-100
|
|
53
|
+
rubricScore: number | null; // 0-100
|
|
54
|
+
criteriaPassed: number;
|
|
55
|
+
criteriaTotal: number;
|
|
56
|
+
rubricRulesPassed: number;
|
|
57
|
+
rubricRulesTotal: number;
|
|
58
|
+
total: number;
|
|
59
|
+
completed: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface AgentCardData {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
channels: string[];
|
|
67
|
+
organization_id?: string;
|
|
68
|
+
system_prompt?: string;
|
|
69
|
+
tools: AgentCardTool[];
|
|
70
|
+
knowledge_bases: AgentCardKnowledgeBase[];
|
|
71
|
+
llm_config?: AgentCardLLMConfig;
|
|
72
|
+
generatedDate: string;
|
|
73
|
+
lifecycle?: LifecycleStage;
|
|
74
|
+
owner?: V1Owner;
|
|
75
|
+
evaluationSummary?: {
|
|
76
|
+
criteriaRate: number | null;
|
|
77
|
+
rubricRate: number | null;
|
|
78
|
+
criteriaPassed: number;
|
|
79
|
+
criteriaTotal: number;
|
|
80
|
+
rubricRulesPassed: number;
|
|
81
|
+
rubricRulesTotal: number;
|
|
82
|
+
totalRuns: number;
|
|
83
|
+
};
|
|
84
|
+
componentScores?: ComponentScores;
|
|
85
|
+
evaluationRuns?: AgentCardEvalRun[];
|
|
86
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|