@thinkhive/sdk 3.1.0 → 3.3.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/README.md +279 -128
- package/dist/api/apiKeys.d.ts +252 -0
- package/dist/api/apiKeys.js +298 -0
- package/dist/api/business-metrics.d.ts +188 -0
- package/dist/api/business-metrics.js +213 -0
- package/dist/api/conversation-eval.d.ts +200 -0
- package/dist/api/conversation-eval.js +235 -0
- package/dist/api/deterministic-graders.d.ts +205 -0
- package/dist/api/deterministic-graders.js +191 -0
- package/dist/api/eval-health.d.ts +250 -0
- package/dist/api/eval-health.js +224 -0
- package/dist/api/human-review.d.ts +275 -0
- package/dist/api/human-review.js +236 -0
- package/dist/api/nondeterminism.d.ts +300 -0
- package/dist/api/nondeterminism.js +250 -0
- package/dist/api/quality-metrics.d.ts +303 -0
- package/dist/api/quality-metrics.js +198 -0
- package/dist/api/roi-analytics.d.ts +263 -0
- package/dist/api/roi-analytics.js +204 -0
- package/dist/api/transcript-patterns.d.ts +204 -0
- package/dist/api/transcript-patterns.js +227 -0
- package/dist/core/client.d.ts +82 -8
- package/dist/core/client.js +223 -32
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +2 -2
- package/dist/core/types.d.ts +27 -2
- package/dist/core/types.js +1 -1
- package/dist/index.d.ts +415 -62
- package/dist/index.js +253 -37
- package/package.json +8 -4
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThinkHive SDK v3.1 - Quality Metrics API
|
|
3
|
+
*
|
|
4
|
+
* RAG Evaluation & Hallucination Detection for AI quality assurance
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Retrieved context for RAG evaluation
|
|
8
|
+
*/
|
|
9
|
+
export interface RetrievedContext {
|
|
10
|
+
content: string;
|
|
11
|
+
chunkIndex?: number;
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
score?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Ground truth context
|
|
17
|
+
*/
|
|
18
|
+
export interface GroundTruthContext {
|
|
19
|
+
content: string;
|
|
20
|
+
chunkIndex?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Grounded span evidence
|
|
24
|
+
*/
|
|
25
|
+
export interface GroundedSpan {
|
|
26
|
+
text: string;
|
|
27
|
+
confidence: number;
|
|
28
|
+
sourceChunkIndex?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Ungrounded span evidence
|
|
32
|
+
*/
|
|
33
|
+
export interface UngroundedSpan {
|
|
34
|
+
text: string;
|
|
35
|
+
confidence: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Citation mapping
|
|
39
|
+
*/
|
|
40
|
+
export interface CitationMap {
|
|
41
|
+
claim: string;
|
|
42
|
+
citedIndex: number;
|
|
43
|
+
isValid: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* RAG evaluation result
|
|
47
|
+
*/
|
|
48
|
+
export interface RAGEvaluation {
|
|
49
|
+
contextRelevance: number;
|
|
50
|
+
contextPrecision: number;
|
|
51
|
+
contextRecall: number;
|
|
52
|
+
groundedness: number;
|
|
53
|
+
faithfulness: number;
|
|
54
|
+
answerRelevance: number;
|
|
55
|
+
citationAccuracy: number;
|
|
56
|
+
citationCompleteness: number;
|
|
57
|
+
overallScore: number;
|
|
58
|
+
grade: 'A' | 'B' | 'C' | 'D' | 'F';
|
|
59
|
+
groundedSpanCount?: number;
|
|
60
|
+
ungroundedSpanCount?: number;
|
|
61
|
+
issues: string[];
|
|
62
|
+
recommendations: string[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* RAG evaluation evidence
|
|
66
|
+
*/
|
|
67
|
+
export interface RAGEvidence {
|
|
68
|
+
groundedSpans: GroundedSpan[];
|
|
69
|
+
ungroundedSpans: UngroundedSpan[];
|
|
70
|
+
citationMap: CitationMap[];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Hallucination instance
|
|
74
|
+
*/
|
|
75
|
+
export interface HallucinationInstance {
|
|
76
|
+
type: string;
|
|
77
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
78
|
+
text: string;
|
|
79
|
+
explanation: string;
|
|
80
|
+
confidence: number;
|
|
81
|
+
suggestedFix?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Hallucination detection report
|
|
85
|
+
*/
|
|
86
|
+
export interface HallucinationReport {
|
|
87
|
+
hasHallucinations: boolean;
|
|
88
|
+
hallucinationScore: number;
|
|
89
|
+
riskLevel: 'low' | 'medium' | 'high' | 'critical';
|
|
90
|
+
factualClaims: number;
|
|
91
|
+
verifiedClaims: number;
|
|
92
|
+
unverifiedClaims: number;
|
|
93
|
+
summary: string;
|
|
94
|
+
recommendations: string[];
|
|
95
|
+
instances: HallucinationInstance[];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Groundedness analysis result
|
|
99
|
+
*/
|
|
100
|
+
export interface GroundednessResult {
|
|
101
|
+
score: number;
|
|
102
|
+
faithfulness: number;
|
|
103
|
+
contextRelevance: number;
|
|
104
|
+
grade: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Batch evaluation result for a single trace
|
|
108
|
+
*/
|
|
109
|
+
export interface BatchEvaluationResult {
|
|
110
|
+
traceId: string;
|
|
111
|
+
success: boolean;
|
|
112
|
+
error?: string;
|
|
113
|
+
rag?: {
|
|
114
|
+
score: number;
|
|
115
|
+
grade: string;
|
|
116
|
+
mainIssue?: string;
|
|
117
|
+
};
|
|
118
|
+
hallucination?: {
|
|
119
|
+
hasIssues: boolean;
|
|
120
|
+
score: number;
|
|
121
|
+
topIssue?: string;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Batch evaluation summary
|
|
126
|
+
*/
|
|
127
|
+
export interface BatchEvaluationSummary {
|
|
128
|
+
totalTraces: number;
|
|
129
|
+
successfulEvaluations: number;
|
|
130
|
+
avgRagScore: number;
|
|
131
|
+
hallucinationRate: number;
|
|
132
|
+
gradeDistribution: {
|
|
133
|
+
A: number;
|
|
134
|
+
B: number;
|
|
135
|
+
C: number;
|
|
136
|
+
D: number;
|
|
137
|
+
F: number;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Quality Metrics API client for RAG evaluation and hallucination detection
|
|
142
|
+
*/
|
|
143
|
+
export declare const qualityMetrics: {
|
|
144
|
+
/**
|
|
145
|
+
* Get RAG quality scores for a specific trace
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* const scores = await qualityMetrics.getRagScores('trace_abc123');
|
|
150
|
+
* console.log(`Groundedness: ${scores.evaluation.groundedness}`);
|
|
151
|
+
* console.log(`Grade: ${scores.evaluation.grade}`);
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
getRagScores(traceId: string): Promise<{
|
|
155
|
+
traceId: string;
|
|
156
|
+
evaluation: RAGEvaluation;
|
|
157
|
+
evidence: RAGEvidence;
|
|
158
|
+
}>;
|
|
159
|
+
/**
|
|
160
|
+
* Get hallucination detection report for a trace
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* const report = await qualityMetrics.getHallucinationReport('trace_abc123');
|
|
165
|
+
* if (report.report.hasHallucinations) {
|
|
166
|
+
* console.log(`Risk level: ${report.report.riskLevel}`);
|
|
167
|
+
* for (const instance of report.report.instances) {
|
|
168
|
+
* console.log(`- ${instance.type}: ${instance.text}`);
|
|
169
|
+
* }
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
getHallucinationReport(traceId: string): Promise<{
|
|
174
|
+
traceId: string;
|
|
175
|
+
report: HallucinationReport;
|
|
176
|
+
}>;
|
|
177
|
+
/**
|
|
178
|
+
* Evaluate RAG quality for provided content (ad-hoc evaluation)
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* const result = await qualityMetrics.evaluateRag({
|
|
183
|
+
* query: 'What is the refund policy?',
|
|
184
|
+
* response: 'You can get a refund within 30 days.',
|
|
185
|
+
* retrievedContexts: [
|
|
186
|
+
* { content: 'Our refund policy allows returns within 30 days of purchase.' },
|
|
187
|
+
* ],
|
|
188
|
+
* });
|
|
189
|
+
* console.log(`Groundedness: ${result.evaluation.groundedness}`);
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
evaluateRag(input: {
|
|
193
|
+
query: string;
|
|
194
|
+
response: string;
|
|
195
|
+
retrievedContexts: RetrievedContext[];
|
|
196
|
+
groundTruthContexts?: GroundTruthContext[];
|
|
197
|
+
citations?: string[];
|
|
198
|
+
}): Promise<{
|
|
199
|
+
evaluation: RAGEvaluation;
|
|
200
|
+
evidence: RAGEvidence;
|
|
201
|
+
}>;
|
|
202
|
+
/**
|
|
203
|
+
* Detect hallucinations in provided content (ad-hoc detection)
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* const result = await qualityMetrics.detectHallucinations({
|
|
208
|
+
* response: 'The product costs $99 and comes with a 2-year warranty.',
|
|
209
|
+
* contexts: [
|
|
210
|
+
* { content: 'The product costs $99 with a 1-year warranty.' },
|
|
211
|
+
* ],
|
|
212
|
+
* });
|
|
213
|
+
* if (result.report.hasHallucinations) {
|
|
214
|
+
* console.log('Detected hallucinations:', result.report.instances);
|
|
215
|
+
* }
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
detectHallucinations(input: {
|
|
219
|
+
response: string;
|
|
220
|
+
contexts: Array<{
|
|
221
|
+
content: string;
|
|
222
|
+
metadata?: Record<string, unknown>;
|
|
223
|
+
}>;
|
|
224
|
+
query?: string;
|
|
225
|
+
previousResponses?: string[];
|
|
226
|
+
}): Promise<{
|
|
227
|
+
report: HallucinationReport;
|
|
228
|
+
}>;
|
|
229
|
+
/**
|
|
230
|
+
* Get groundedness analysis for a trace
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* const result = await qualityMetrics.getGroundedness('trace_abc123');
|
|
235
|
+
* console.log(`Groundedness score: ${result.groundedness.score}`);
|
|
236
|
+
* console.log(`Grounded spans: ${result.summary.groundedSpans}`);
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
getGroundedness(traceId: string): Promise<{
|
|
240
|
+
traceId: string;
|
|
241
|
+
groundedness: GroundednessResult;
|
|
242
|
+
spans: {
|
|
243
|
+
grounded: Array<{
|
|
244
|
+
text: string;
|
|
245
|
+
confidence: number;
|
|
246
|
+
sourceIndex: number;
|
|
247
|
+
}>;
|
|
248
|
+
ungrounded: Array<{
|
|
249
|
+
text: string;
|
|
250
|
+
confidence: number;
|
|
251
|
+
}>;
|
|
252
|
+
};
|
|
253
|
+
summary: {
|
|
254
|
+
totalSpans: number;
|
|
255
|
+
groundedSpans: number;
|
|
256
|
+
ungroundedSpans: number;
|
|
257
|
+
groundednessRatio: number;
|
|
258
|
+
};
|
|
259
|
+
}>;
|
|
260
|
+
/**
|
|
261
|
+
* Evaluate multiple traces for quality metrics in batch
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* const result = await qualityMetrics.evaluateBatch({
|
|
266
|
+
* traceIds: ['trace_1', 'trace_2', 'trace_3'],
|
|
267
|
+
* });
|
|
268
|
+
* console.log(`Average RAG score: ${result.summary.avgRagScore}`);
|
|
269
|
+
* console.log(`Hallucination rate: ${result.summary.hallucinationRate}%`);
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
evaluateBatch(options: {
|
|
273
|
+
traceIds: string[];
|
|
274
|
+
includeDetails?: boolean;
|
|
275
|
+
}): Promise<{
|
|
276
|
+
summary: BatchEvaluationSummary;
|
|
277
|
+
results: BatchEvaluationResult[];
|
|
278
|
+
}>;
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* Check if a RAG evaluation passes quality thresholds
|
|
282
|
+
*/
|
|
283
|
+
export declare function passesQualityThreshold(evaluation: RAGEvaluation, thresholds?: {
|
|
284
|
+
minGroundedness?: number;
|
|
285
|
+
minOverallScore?: number;
|
|
286
|
+
minGrade?: 'A' | 'B' | 'C' | 'D';
|
|
287
|
+
}): boolean;
|
|
288
|
+
/**
|
|
289
|
+
* Check if hallucination risk is acceptable
|
|
290
|
+
*/
|
|
291
|
+
export declare function isHallucinationRiskAcceptable(report: HallucinationReport, maxRiskLevel?: 'low' | 'medium' | 'high'): boolean;
|
|
292
|
+
/**
|
|
293
|
+
* Get quality recommendations based on evaluation
|
|
294
|
+
*/
|
|
295
|
+
export declare function getQualityRecommendations(ragEval: RAGEvaluation, hallucinationReport?: HallucinationReport): string[];
|
|
296
|
+
/**
|
|
297
|
+
* Format quality score for display
|
|
298
|
+
*/
|
|
299
|
+
export declare function formatQualityScore(score: number): string;
|
|
300
|
+
/**
|
|
301
|
+
* Get color indicator for grade
|
|
302
|
+
*/
|
|
303
|
+
export declare function getGradeColor(grade: 'A' | 'B' | 'C' | 'D' | 'F'): 'green' | 'blue' | 'yellow' | 'orange' | 'red';
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ThinkHive SDK v3.1 - Quality Metrics API
|
|
4
|
+
*
|
|
5
|
+
* RAG Evaluation & Hallucination Detection for AI quality assurance
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.qualityMetrics = void 0;
|
|
9
|
+
exports.passesQualityThreshold = passesQualityThreshold;
|
|
10
|
+
exports.isHallucinationRiskAcceptable = isHallucinationRiskAcceptable;
|
|
11
|
+
exports.getQualityRecommendations = getQualityRecommendations;
|
|
12
|
+
exports.formatQualityScore = formatQualityScore;
|
|
13
|
+
exports.getGradeColor = getGradeColor;
|
|
14
|
+
const client_1 = require("../core/client");
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// QUALITY METRICS API CLIENT
|
|
17
|
+
// ============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Quality Metrics API client for RAG evaluation and hallucination detection
|
|
20
|
+
*/
|
|
21
|
+
exports.qualityMetrics = {
|
|
22
|
+
/**
|
|
23
|
+
* Get RAG quality scores for a specific trace
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const scores = await qualityMetrics.getRagScores('trace_abc123');
|
|
28
|
+
* console.log(`Groundedness: ${scores.evaluation.groundedness}`);
|
|
29
|
+
* console.log(`Grade: ${scores.evaluation.grade}`);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
async getRagScores(traceId) {
|
|
33
|
+
return (0, client_1.apiRequestWithData)(`/quality/rag-scores/${traceId}`, {
|
|
34
|
+
apiVersion: 'v1',
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Get hallucination detection report for a trace
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const report = await qualityMetrics.getHallucinationReport('trace_abc123');
|
|
43
|
+
* if (report.report.hasHallucinations) {
|
|
44
|
+
* console.log(`Risk level: ${report.report.riskLevel}`);
|
|
45
|
+
* for (const instance of report.report.instances) {
|
|
46
|
+
* console.log(`- ${instance.type}: ${instance.text}`);
|
|
47
|
+
* }
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
async getHallucinationReport(traceId) {
|
|
52
|
+
return (0, client_1.apiRequestWithData)(`/quality/hallucination-report/${traceId}`, {
|
|
53
|
+
apiVersion: 'v1',
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* Evaluate RAG quality for provided content (ad-hoc evaluation)
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const result = await qualityMetrics.evaluateRag({
|
|
62
|
+
* query: 'What is the refund policy?',
|
|
63
|
+
* response: 'You can get a refund within 30 days.',
|
|
64
|
+
* retrievedContexts: [
|
|
65
|
+
* { content: 'Our refund policy allows returns within 30 days of purchase.' },
|
|
66
|
+
* ],
|
|
67
|
+
* });
|
|
68
|
+
* console.log(`Groundedness: ${result.evaluation.groundedness}`);
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
async evaluateRag(input) {
|
|
72
|
+
return (0, client_1.apiRequestWithData)('/quality/evaluate-rag', {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
body: input,
|
|
75
|
+
apiVersion: 'v1',
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* Detect hallucinations in provided content (ad-hoc detection)
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const result = await qualityMetrics.detectHallucinations({
|
|
84
|
+
* response: 'The product costs $99 and comes with a 2-year warranty.',
|
|
85
|
+
* contexts: [
|
|
86
|
+
* { content: 'The product costs $99 with a 1-year warranty.' },
|
|
87
|
+
* ],
|
|
88
|
+
* });
|
|
89
|
+
* if (result.report.hasHallucinations) {
|
|
90
|
+
* console.log('Detected hallucinations:', result.report.instances);
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
async detectHallucinations(input) {
|
|
95
|
+
return (0, client_1.apiRequestWithData)('/quality/detect-hallucinations', {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
body: input,
|
|
98
|
+
apiVersion: 'v1',
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* Get groundedness analysis for a trace
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const result = await qualityMetrics.getGroundedness('trace_abc123');
|
|
107
|
+
* console.log(`Groundedness score: ${result.groundedness.score}`);
|
|
108
|
+
* console.log(`Grounded spans: ${result.summary.groundedSpans}`);
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
async getGroundedness(traceId) {
|
|
112
|
+
return (0, client_1.apiRequestWithData)(`/quality/groundedness/${traceId}`, {
|
|
113
|
+
apiVersion: 'v1',
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
/**
|
|
117
|
+
* Evaluate multiple traces for quality metrics in batch
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* const result = await qualityMetrics.evaluateBatch({
|
|
122
|
+
* traceIds: ['trace_1', 'trace_2', 'trace_3'],
|
|
123
|
+
* });
|
|
124
|
+
* console.log(`Average RAG score: ${result.summary.avgRagScore}`);
|
|
125
|
+
* console.log(`Hallucination rate: ${result.summary.hallucinationRate}%`);
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
async evaluateBatch(options) {
|
|
129
|
+
return (0, client_1.apiRequestWithData)('/quality/evaluate-batch', {
|
|
130
|
+
method: 'POST',
|
|
131
|
+
body: options,
|
|
132
|
+
apiVersion: 'v1',
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// HELPER FUNCTIONS
|
|
138
|
+
// ============================================================================
|
|
139
|
+
/**
|
|
140
|
+
* Check if a RAG evaluation passes quality thresholds
|
|
141
|
+
*/
|
|
142
|
+
function passesQualityThreshold(evaluation, thresholds = {}) {
|
|
143
|
+
const { minGroundedness = 0.7, minOverallScore = 60, minGrade = 'C' } = thresholds;
|
|
144
|
+
const gradeOrder = { A: 4, B: 3, C: 2, D: 1, F: 0 };
|
|
145
|
+
const meetsGroundedness = evaluation.groundedness >= minGroundedness;
|
|
146
|
+
const meetsScore = evaluation.overallScore >= minOverallScore;
|
|
147
|
+
const meetsGrade = gradeOrder[evaluation.grade] >= gradeOrder[minGrade];
|
|
148
|
+
return meetsGroundedness && meetsScore && meetsGrade;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check if hallucination risk is acceptable
|
|
152
|
+
*/
|
|
153
|
+
function isHallucinationRiskAcceptable(report, maxRiskLevel = 'medium') {
|
|
154
|
+
const riskOrder = { low: 0, medium: 1, high: 2, critical: 3 };
|
|
155
|
+
return riskOrder[report.riskLevel] <= riskOrder[maxRiskLevel];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get quality recommendations based on evaluation
|
|
159
|
+
*/
|
|
160
|
+
function getQualityRecommendations(ragEval, hallucinationReport) {
|
|
161
|
+
const recommendations = [];
|
|
162
|
+
if (ragEval.groundedness < 0.7) {
|
|
163
|
+
recommendations.push('Improve grounding by increasing context relevance');
|
|
164
|
+
}
|
|
165
|
+
if (ragEval.contextRelevance < 0.6) {
|
|
166
|
+
recommendations.push('Tune retrieval to return more relevant contexts');
|
|
167
|
+
}
|
|
168
|
+
if (ragEval.citationAccuracy < 0.8) {
|
|
169
|
+
recommendations.push('Improve citation accuracy in responses');
|
|
170
|
+
}
|
|
171
|
+
if (hallucinationReport?.hasHallucinations) {
|
|
172
|
+
recommendations.push('Add fact-checking layer to reduce hallucinations');
|
|
173
|
+
}
|
|
174
|
+
if (recommendations.length === 0) {
|
|
175
|
+
recommendations.push('Quality metrics are within acceptable ranges');
|
|
176
|
+
}
|
|
177
|
+
return recommendations;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Format quality score for display
|
|
181
|
+
*/
|
|
182
|
+
function formatQualityScore(score) {
|
|
183
|
+
return `${Math.round(score * 100)}%`;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get color indicator for grade
|
|
187
|
+
*/
|
|
188
|
+
function getGradeColor(grade) {
|
|
189
|
+
const colors = {
|
|
190
|
+
A: 'green',
|
|
191
|
+
B: 'blue',
|
|
192
|
+
C: 'yellow',
|
|
193
|
+
D: 'orange',
|
|
194
|
+
F: 'red',
|
|
195
|
+
};
|
|
196
|
+
return colors[grade];
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVhbGl0eS1tZXRyaWNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwaS9xdWFsaXR5LW1ldHJpY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7O0dBSUc7OztBQXFWSCx3REFnQkM7QUFLRCxzRUFNQztBQUtELDhEQTJCQztBQUtELGdEQUVDO0FBS0Qsc0NBV0M7QUFyYUQsMkNBQWdFO0FBa0toRSwrRUFBK0U7QUFDL0UsNkJBQTZCO0FBQzdCLCtFQUErRTtBQUUvRTs7R0FFRztBQUNVLFFBQUEsY0FBYyxHQUFHO0lBQzVCOzs7Ozs7Ozs7T0FTRztJQUNILEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBZTtRQUtoQyxPQUFPLElBQUEsMkJBQWtCLEVBQUMsdUJBQXVCLE9BQU8sRUFBRSxFQUFFO1lBQzFELFVBQVUsRUFBRSxJQUFJO1NBQ2pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7OztPQWFHO0lBQ0gsS0FBSyxDQUFDLHNCQUFzQixDQUFDLE9BQWU7UUFJMUMsT0FBTyxJQUFBLDJCQUFrQixFQUFDLGlDQUFpQyxPQUFPLEVBQUUsRUFBRTtZQUNwRSxVQUFVLEVBQUUsSUFBSTtTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDSCxLQUFLLENBQUMsV0FBVyxDQUFDLEtBTWpCO1FBSUMsT0FBTyxJQUFBLDJCQUFrQixFQUFDLHVCQUF1QixFQUFFO1lBQ2pELE1BQU0sRUFBRSxNQUFNO1lBQ2QsSUFBSSxFQUFFLEtBQUs7WUFDWCxVQUFVLEVBQUUsSUFBSTtTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0gsS0FBSyxDQUFDLG9CQUFvQixDQUFDLEtBSzFCO1FBR0MsT0FBTyxJQUFBLDJCQUFrQixFQUFDLGdDQUFnQyxFQUFFO1lBQzFELE1BQU0sRUFBRSxNQUFNO1lBQ2QsSUFBSSxFQUFFLEtBQUs7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O0dBRUc7QUFDSCxTQUFnQixrQkFBa0IsQ0FBQyxLQUFhO0lBQzlDLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDO0FBQ3ZDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLGFBQWEsQ0FDM0IsS0FBa0M7SUFFbEMsTUFBTSxNQUFNLEdBQUc7UUFDYixDQUFDLEVBQUUsT0FBZ0I7UUFDbkIsQ0FBQyxFQUFFLE1BQWU7UUFDbEIsQ0FBQyxFQUFFLFFBQWlCO1FBQ3BCLENBQUMsRUFBRSxRQUFpQjtRQUNwQixDQUFDLEVBQUUsS0FBYztLQUNsQixDQUFDO0lBQ0YsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhpbmtIaXZlIFNESyB2My4xIC0gUXVhbGl0eSBNZXRyaWNzIEFQSVxuICpcbiAqIFJBRyBFdmFsdWF0aW9uICYgSGFsbHVjaW5hdGlvbiBEZXRlY3Rpb24gZm9yIEFJIHF1YWxpdHkgYXNzdXJhbmNlXG4gKi9cblxuaW1wb3J0IHsgYXBpUmVxdWVzdCwgYXBpUmVxdWVzdFdpdGhEYXRhIH0gZnJvbSAnLi4vY29yZS9jbGllbnQnO1xuaW1wb3J0IHR5cGUgeyBBcGlSZXNwb25zZSB9IGZyb20gJy4uL2NvcmUvdHlwZXMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFJldHJpZXZlZCBjb250ZXh0IGZvciBSQUcgZXZhbHVhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJldHJpZXZlZENvbnRleHQge1xuICBjb250ZW50OiBzdHJpbmc7XG4gIGNodW5rSW5kZXg/OiBudW1iZXI7XG4gIG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHNjb3JlPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEdyb3VuZCB0cnV0aCBjb250ZXh0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR3JvdW5kVHJ1dGhDb250ZXh0IHtcbiAgY29udGVudDogc3RyaW5nO1xuICBjaHVua0luZGV4PzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEdyb3VuZGVkIHNwYW4gZXZpZGVuY2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHcm91bmRlZFNwYW4ge1xuICB0ZXh0OiBzdHJpbmc7XG4gIGNvbmZpZGVuY2U6IG51bWJlcjtcbiAgc291cmNlQ2h1bmtJbmRleD86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBVbmdyb3VuZGVkIHNwYW4gZXZpZGVuY2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVbmdyb3VuZGVkU3BhbiB7XG4gIHRleHQ6IHN0cmluZztcbiAgY29uZmlkZW5jZTogbnVtYmVyO1xufVxuXG4vKipcbiAqIENpdGF0aW9uIG1hcHBpbmdcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDaXRhdGlvbk1hcCB7XG4gIGNsYWltOiBzdHJpbmc7XG4gIGNpdGVkSW5kZXg6IG51bWJlcjtcbiAgaXNWYWxpZDogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSQUcgZXZhbHVhdGlvbiByZXN1bHRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSQUdFdmFsdWF0aW9uIHtcbiAgLy8gUmV0cmlldmFsIFF1YWxpdHlcbiAgY29udGV4dFJlbGV2YW5jZTogbnVtYmVyO1xuICBjb250ZXh0UHJlY2lzaW9uOiBudW1iZXI7XG4gIGNvbnRleHRSZWNhbGw6IG51bWJlcjtcblxuICAvLyBHZW5lcmF0aW9uIFF1YWxpdHlcbiAgZ3JvdW5kZWRuZXNzOiBudW1iZXI7XG4gIGZhaXRoZnVsbmVzczogbnVtYmVyO1xuICBhbnN3ZXJSZWxldmFuY2U6IG51bWJlcjtcblxuICAvLyBDaXRhdGlvbiBRdWFsaXR5XG4gIGNpdGF0aW9uQWNjdXJhY3k6IG51bWJlcjtcbiAgY2l0YXRpb25Db21wbGV0ZW5lc3M6IG51bWJlcjtcblxuICAvLyBPdmVyYWxsXG4gIG92ZXJhbGxTY29yZTogbnVtYmVyO1xuICBncmFkZTogJ0EnIHwgJ0InIHwgJ0MnIHwgJ0QnIHwgJ0YnO1xuXG4gIC8vIERldGFpbHNcbiAgZ3JvdW5kZWRTcGFuQ291bnQ/OiBudW1iZXI7XG4gIHVuZ3JvdW5kZWRTcGFuQ291bnQ/OiBudW1iZXI7XG4gIGlzc3Vlczogc3RyaW5nW107XG4gIHJlY29tbWVuZGF0aW9uczogc3RyaW5nW107XG59XG5cbi8qKlxuICogUkFHIGV2YWx1YXRpb24gZXZpZGVuY2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSQUdFdmlkZW5jZSB7XG4gIGdyb3VuZGVkU3BhbnM6IEdyb3VuZGVkU3BhbltdO1xuICB1bmdyb3VuZGVkU3BhbnM6IFVuZ3JvdW5kZWRTcGFuW107XG4gIGNpdGF0aW9uTWFwOiBDaXRhdGlvbk1hcFtdO1xufVxuXG4vKipcbiAqIEhhbGx1Y2luYXRpb24gaW5zdGFuY2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBIYWxsdWNpbmF0aW9uSW5zdGFuY2Uge1xuICB0eXBlOiBzdHJpbmc7XG4gIHNldmVyaXR5OiAnbG93JyB8ICdtZWRpdW0nIHwgJ2hpZ2gnIHwgJ2NyaXRpY2FsJztcbiAgdGV4dDogc3RyaW5nO1xuICBleHBsYW5hdGlvbjogc3RyaW5nO1xuICBjb25maWRlbmNlOiBudW1iZXI7XG4gIHN1Z2dlc3RlZEZpeD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBIYWxsdWNpbmF0aW9uIGRldGVjdGlvbiByZXBvcnRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBIYWxsdWNpbmF0aW9uUmVwb3J0IHtcbiAgaGFzSGFsbHVjaW5hdGlvbnM6IGJvb2xlYW47XG4gIGhhbGx1Y2luYXRpb25TY29yZTogbnVtYmVyO1xuICByaXNrTGV2ZWw6ICdsb3cnIHwgJ21lZGl1bScgfCAnaGlnaCcgfCAnY3JpdGljYWwnO1xuICBmYWN0dWFsQ2xhaW1zOiBudW1iZXI7XG4gIHZlcmlmaWVkQ2xhaW1zOiBudW1iZXI7XG4gIHVudmVyaWZpZWRDbGFpbXM6IG51bWJlcjtcbiAgc3VtbWFyeTogc3RyaW5nO1xuICByZWNvbW1lbmRhdGlvbnM6IHN0cmluZ1tdO1xuICBpbnN0YW5jZXM6IEhhbGx1Y2luYXRpb25JbnN0YW5jZVtdO1xufVxuXG4vKipcbiAqIEdyb3VuZGVkbmVzcyBhbmFseXNpcyByZXN1bHRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHcm91bmRlZG5lc3NSZXN1bHQge1xuICBzY29yZTogbnVtYmVyO1xuICBmYWl0aGZ1bG5lc3M6IG51bWJlcjtcbiAgY29udGV4dFJlbGV2YW5jZTogbnVtYmVyO1xuICBncmFkZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIEJhdGNoIGV2YWx1YXRpb24gcmVzdWx0IGZvciBhIHNpbmdsZSB0cmFjZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhdGNoRXZhbHVhdGlvblJlc3VsdCB7XG4gIHRyYWNlSWQ6IHN0cmluZztcbiAgc3VjY2VzczogYm9vbGVhbjtcbiAgZXJyb3I/OiBzdHJpbmc7XG4gIHJhZz86IHtcbiAgICBzY29yZTogbnVtYmVyO1xuICAgIGdyYWRlOiBzdHJpbmc7XG4gICAgbWFpbklzc3VlPzogc3RyaW5nO1xuICB9O1xuICBoYWxsdWNpbmF0aW9uPzoge1xuICAgIGhhc0lzc3VlczogYm9vbGVhbjtcbiAgICBzY29yZTogbnVtYmVyO1xuICAgIHRvcElzc3VlPzogc3RyaW5nO1xuICB9O1xufVxuXG4vKipcbiAqIEJhdGNoIGV2YWx1YXRpb24gc3VtbWFyeVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhdGNoRXZhbHVhdGlvblN1bW1hcnkge1xuICB0b3RhbFRyYWNlczogbnVtYmVyO1xuICBzdWNjZXNzZnVsRXZhbHVhdGlvbnM6IG51bWJlcjtcbiAgYXZnUmFnU2NvcmU6IG51bWJlcjtcbiAgaGFsbHVjaW5hdGlvblJhdGU6IG51bWJlcjtcbiAgZ3JhZGVEaXN0cmlidXRpb246IHtcbiAgICBBOiBudW1iZXI7XG4gICAgQjogbnVtYmVyO1xuICAgIEM6IG51bWJlcjtcbiAgICBEOiBudW1iZXI7XG4gICAgRjogbnVtYmVyO1xuICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBRVUFMSVRZIE1FVFJJQ1MgQVBJIENMSUVOVFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFF1YWxpdHkgTWV0cmljcyBBUEkgY2xpZW50IGZvciBSQUcgZXZhbHVhdGlvbiBhbmQgaGFsbHVjaW5hdGlvbiBkZXRlY3Rpb25cbiAqL1xuZXhwb3J0IGNvbnN0IHF1YWxpdHlNZXRyaWNzID0ge1xuICAvKipcbiAgICogR2V0IFJBRyBxdWFsaXR5IHNjb3JlcyBmb3IgYSBzcGVjaWZpYyB0cmFjZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHNjb3JlcyA9IGF3YWl0IHF1YWxpdHlNZXRyaWNzLmdldFJhZ1Njb3JlcygndHJhY2VfYWJjMTIzJyk7XG4gICAqIGNvbnNvbGUubG9nKGBHcm91bmRlZG5lc3M6ICR7c2NvcmVzLmV2YWx1YXRpb24uZ3JvdW5kZWRuZXNzfWApO1xuICAgKiBjb25zb2xlLmxvZyhgR3JhZGU6ICR7c2NvcmVzLmV2YWx1YXRpb24uZ3JhZGV9YCk7XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgZ2V0UmFnU2NvcmVzKHRyYWNlSWQ6IHN0cmluZyk6IFByb21pc2U8e1xuICAgIHRyYWNlSWQ6IHN0cmluZztcbiAgICBldmFsdWF0aW9uOiBSQUdFdmFsdWF0aW9uO1xuICAgIGV2aWRlbmNlOiBSQUdFdmlkZW5jZTtcbiAgfT4ge1xuICAgIHJldHVybiBhcGlSZXF1ZXN0V2l0aERhdGEoYC9xdWFsaXR5L3JhZy1zY29yZXMvJHt0cmFjZUlkfWAsIHtcbiAgICAgIGFwaVZlcnNpb246ICd2MScsXG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBoYWxsdWNpbmF0aW9uIGRldGVjdGlvbiByZXBvcnQgZm9yIGEgdHJhY2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCByZXBvcnQgPSBhd2FpdCBxdWFsaXR5TWV0cmljcy5nZXRIYWxsdWNpbmF0aW9uUmVwb3J0KCd0cmFjZV9hYmMxMjMnKTtcbiAgICogaWYgKHJlcG9ydC5yZXBvcnQuaGFzSGFsbHVjaW5hdGlvbnMpIHtcbiAgICogICBjb25zb2xlLmxvZyhgUmlzayBsZXZlbDogJHtyZXBvcnQucmVwb3J0LnJpc2tMZXZlbH1gKTtcbiAgICogICBmb3IgKGNvbnN0IGluc3RhbmNlIG9mIHJlcG9ydC5yZXBvcnQuaW5zdGFuY2VzKSB7XG4gICAqICAgICBjb25zb2xlLmxvZyhgLSAke2luc3RhbmNlLnR5cGV9OiAke2luc3RhbmNlLnRleHR9YCk7XG4gICAqICAgfVxuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgZ2V0SGFsbHVjaW5hdGlvblJlcG9ydCh0cmFjZUlkOiBzdHJpbmcpOiBQcm9taXNlPHtcbiAgICB0cmFjZUlkOiBzdHJpbmc7XG4gICAgcmVwb3J0OiBIYWxsdWNpbmF0aW9uUmVwb3J0O1xuICB9PiB7XG4gICAgcmV0dXJuIGFwaVJlcXVlc3RXaXRoRGF0YShgL3F1YWxpdHkvaGFsbHVjaW5hdGlvbi1yZXBvcnQvJHt0cmFjZUlkfWAsIHtcbiAgICAgIGFwaVZlcnNpb246ICd2MScsXG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEV2YWx1YXRlIFJBRyBxdWFsaXR5IGZvciBwcm92aWRlZCBjb250ZW50IChhZC1ob2MgZXZhbHVhdGlvbilcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBxdWFsaXR5TWV0cmljcy5ldmFsdWF0ZVJhZyh7XG4gICAqICAgcXVlcnk6ICdXaGF0IGlzIHRoZSByZWZ1bmQgcG9saWN5PycsXG4gICAqICAgcmVzcG9uc2U6ICdZb3UgY2FuIGdldCBhIHJlZnVuZCB3aXRoaW4gMzAgZGF5cy4nLFxuICAgKiAgIHJldHJpZXZlZENvbnRleHRzOiBbXG4gICAqICAgICB7IGNvbnRlbnQ6ICdPdXIgcmVmdW5kIHBvbGljeSBhbGxvd3MgcmV0dXJucyB3aXRoaW4gMzAgZGF5cyBvZiBwdXJjaGFzZS4nIH0sXG4gICAqICAgXSxcbiAgICogfSk7XG4gICAqIGNvbnNvbGUubG9nKGBHcm91bmRlZG5lc3M6ICR7cmVzdWx0LmV2YWx1YXRpb24uZ3JvdW5kZWRuZXNzfWApO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGV2YWx1YXRlUmFnKGlucHV0OiB7XG4gICAgcXVlcnk6IHN0cmluZztcbiAgICByZXNwb25zZTogc3RyaW5nO1xuICAgIHJldHJpZXZlZENvbnRleHRzOiBSZXRyaWV2ZWRDb250ZXh0W107XG4gICAgZ3JvdW5kVHJ1dGhDb250ZXh0cz86IEdyb3VuZFRydXRoQ29udGV4dFtdO1xuICAgIGNpdGF0aW9ucz86IHN0cmluZ1tdO1xuICB9KTogUHJvbWlzZTx7XG4gICAgZXZhbHVhdGlvbjogUkFHRXZhbHVhdGlvbjtcbiAgICBldmlkZW5jZTogUkFHRXZpZGVuY2U7XG4gIH0+IHtcbiAgICByZXR1cm4gYXBpUmVxdWVzdFdpdGhEYXRhKCcvcXVhbGl0eS9ldmFsdWF0ZS1yYWcnLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGJvZHk6IGlucHV0LFxuICAgICAgYXBpVmVyc2lvbjogJ3YxJyxcbiAgICB9KTtcbiAgfSxcblxuICAvKipcbiAgICogRGV0ZWN0IGhhbGx1Y2luYXRpb25zIGluIHByb3ZpZGVkIGNvbnRlbnQgKGFkLWhvYyBkZXRlY3Rpb24pXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgcmVzdWx0ID0gYXdhaXQgcXVhbGl0eU1ldHJpY3MuZGV0ZWN0SGFsbHVjaW5hdGlvbnMoe1xuICAgKiAgIHJlc3BvbnNlOiAnVGhlIHByb2R1Y3QgY29zdHMgJDk5IGFuZCBjb21lcyB3aXRoIGEgMi15ZWFyIHdhcnJhbnR5LicsXG4gICAqICAgY29udGV4dHM6IFtcbiAgICogICAgIHsgY29udGVudDogJ1RoZSBwcm9kdWN0IGNvc3RzICQ5OSB3aXRoIGEgMS15ZWFyIHdhcnJhbnR5LicgfSxcbiAgICogICBdLFxuICAgKiB9KTtcbiAgICogaWYgKHJlc3VsdC5yZXBvcnQuaGFzSGFsbHVjaW5hdGlvbnMpIHtcbiAgICogICBjb25zb2xlLmxvZygnRGV0ZWN0ZWQgaGFsbHVjaW5hdGlvbnM6JywgcmVzdWx0LnJlcG9ydC5pbnN0YW5jZXMpO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgZGV0ZWN0SGFsbHVjaW5hdGlvbnMoaW5wdXQ6IHtcbiAgICByZXNwb25zZTogc3RyaW5nO1xuICAgIGNvbnRleHRzOiBBcnJheTx7IGNvbnRlbnQ6IHN0cmluZzsgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9PjtcbiAgICBxdWVyeT86IHN0cmluZztcbiAgICBwcmV2aW91c1Jlc3BvbnNlcz86IHN0cmluZ1tdO1xuICB9KTogUHJvbWlzZTx7XG4gICAgcmVwb3J0OiBIYWxsdWNpbmF0aW9uUmVwb3J0O1xuICB9PiB7XG4gICAgcmV0dXJuIGFwaVJlcXVlc3RXaXRoRGF0YSgnL3F1YWxpdHkvZGV0ZWN0LWhhbGx1Y2luYXRpb25zJywge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5OiBpbnB1dCxcbiAgICAgIGFwaVZlcnNpb246ICd2MScsXG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBncm91bmRlZG5lc3MgYW5hbHlzaXMgZm9yIGEgdHJhY2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBxdWFsaXR5TWV0cmljcy5nZXRHcm91bmRlZG5lc3MoJ3RyYWNlX2FiYzEyMycpO1xuICAgKiBjb25zb2xlLmxvZyhgR3JvdW5kZWRuZXNzIHNjb3JlOiAke3Jlc3VsdC5ncm91bmRlZG5lc3Muc2NvcmV9YCk7XG4gICAqIGNvbnNvbGUubG9nKGBHcm91bmRlZCBzcGFuczogJHtyZXN1bHQuc3VtbWFyeS5ncm91bmRlZFNwYW5zfWApO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGdldEdyb3VuZGVkbmVzcyh0cmFjZUlkOiBzdHJpbmcpOiBQcm9taXNlPHtcbiAgICB0cmFjZUlkOiBzdHJpbmc7XG4gICAgZ3JvdW5kZWRuZXNzOiBHcm91bmRlZG5lc3NSZXN1bHQ7XG4gICAgc3BhbnM6IHtcbiAgICAgIGdyb3VuZGVkOiBBcnJheTx7IHRleHQ6IHN0cmluZzsgY29uZmlkZW5jZTogbnVtYmVyOyBzb3VyY2VJbmRleDogbnVtYmVyIH0+O1xuICAgICAgdW5ncm91bmRlZDogQXJyYXk8eyB0ZXh0OiBzdHJpbmc7IGNvbmZpZGVuY2U6IG51bWJlciB9PjtcbiAgICB9O1xuICAgIHN1bW1hcnk6IHtcbiAgICAgIHRvdGFsU3BhbnM6IG51bWJlcjtcbiAgICAgIGdyb3VuZGVkU3BhbnM6IG51bWJlcjtcbiAgICAgIHVuZ3JvdW5kZWRTcGFuczogbnVtYmVyO1xuICAgICAgZ3JvdW5kZWRuZXNzUmF0aW86IG51bWJlcjtcbiAgICB9O1xuICB9PiB7XG4gICAgcmV0dXJuIGFwaVJlcXVlc3RXaXRoRGF0YShgL3F1YWxpdHkvZ3JvdW5kZWRuZXNzLyR7dHJhY2VJZH1gLCB7XG4gICAgICBhcGlWZXJzaW9uOiAndjEnLFxuICAgIH0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZSBtdWx0aXBsZSB0cmFjZXMgZm9yIHF1YWxpdHkgbWV0cmljcyBpbiBiYXRjaFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1YWxpdHlNZXRyaWNzLmV2YWx1YXRlQmF0Y2goe1xuICAgKiAgIHRyYWNlSWRzOiBbJ3RyYWNlXzEnLCAndHJhY2VfMicsICd0cmFjZV8zJ10sXG4gICAqIH0pO1xuICAgKiBjb25zb2xlLmxvZyhgQXZlcmFnZSBSQUcgc2NvcmU6ICR7cmVzdWx0LnN1bW1hcnkuYXZnUmFnU2NvcmV9YCk7XG4gICAqIGNvbnNvbGUubG9nKGBIYWxsdWNpbmF0aW9uIHJhdGU6ICR7cmVzdWx0LnN1bW1hcnkuaGFsbHVjaW5hdGlvblJhdGV9JWApO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGV2YWx1YXRlQmF0Y2gob3B0aW9uczoge1xuICAgIHRyYWNlSWRzOiBzdHJpbmdbXTtcbiAgICBpbmNsdWRlRGV0YWlscz86IGJvb2xlYW47XG4gIH0pOiBQcm9taXNlPHtcbiAgICBzdW1tYXJ5OiBCYXRjaEV2YWx1YXRpb25TdW1tYXJ5O1xuICAgIHJlc3VsdHM6IEJhdGNoRXZhbHVhdGlvblJlc3VsdFtdO1xuICB9PiB7XG4gICAgcmV0dXJuIGFwaVJlcXVlc3RXaXRoRGF0YSgnL3F1YWxpdHkvZXZhbHVhdGUtYmF0Y2gnLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgICBhcGlWZXJzaW9uOiAndjEnLFxuICAgIH0pO1xuICB9LFxufTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENoZWNrIGlmIGEgUkFHIGV2YWx1YXRpb24gcGFzc2VzIHF1YWxpdHkgdGhyZXNob2xkc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGFzc2VzUXVhbGl0eVRocmVzaG9sZChcbiAgZXZhbHVhdGlvbjogUkFHRXZhbHVhdGlvbixcbiAgdGhyZXNob2xkczoge1xuICAgIG1pbkdyb3VuZGVkbmVzcz86IG51bWJlcjtcbiAgICBtaW5PdmVyYWxsU2NvcmU/OiBudW1iZXI7XG4gICAgbWluR3JhZGU/OiAnQScgfCAnQicgfCAnQycgfCAnRCc7XG4gIH0gPSB7fVxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IHsgbWluR3JvdW5kZWRuZXNzID0gMC43LCBtaW5PdmVyYWxsU2NvcmUgPSA2MCwgbWluR3JhZGUgPSAnQycgfSA9IHRocmVzaG9sZHM7XG5cbiAgY29uc3QgZ3JhZGVPcmRlciA9IHsgQTogNCwgQjogMywgQzogMiwgRDogMSwgRjogMCB9O1xuICBjb25zdCBtZWV0c0dyb3VuZGVkbmVzcyA9IGV2YWx1YXRpb24uZ3JvdW5kZWRuZXNzID49IG1pbkdyb3VuZGVkbmVzcztcbiAgY29uc3QgbWVldHNTY29yZSA9IGV2YWx1YXRpb24ub3ZlcmFsbFNjb3JlID49IG1pbk92ZXJhbGxTY29yZTtcbiAgY29uc3QgbWVldHNHcmFkZSA9IGdyYWRlT3JkZXJbZXZhbHVhdGlvbi5ncmFkZV0gPj0gZ3JhZGVPcmRlclttaW5HcmFkZV07XG5cbiAgcmV0dXJuIG1lZXRzR3JvdW5kZWRuZXNzICYmIG1lZXRzU2NvcmUgJiYgbWVldHNHcmFkZTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBoYWxsdWNpbmF0aW9uIHJpc2sgaXMgYWNjZXB0YWJsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNIYWxsdWNpbmF0aW9uUmlza0FjY2VwdGFibGUoXG4gIHJlcG9ydDogSGFsbHVjaW5hdGlvblJlcG9ydCxcbiAgbWF4Umlza0xldmVsOiAnbG93JyB8ICdtZWRpdW0nIHwgJ2hpZ2gnID0gJ21lZGl1bSdcbik6IGJvb2xlYW4ge1xuICBjb25zdCByaXNrT3JkZXIgPSB7IGxvdzogMCwgbWVkaXVtOiAxLCBoaWdoOiAyLCBjcml0aWNhbDogMyB9O1xuICByZXR1cm4gcmlza09yZGVyW3JlcG9ydC5yaXNrTGV2ZWxdIDw9IHJpc2tPcmRlclttYXhSaXNrTGV2ZWxdO1xufVxuXG4vKipcbiAqIEdldCBxdWFsaXR5IHJlY29tbWVuZGF0aW9ucyBiYXNlZCBvbiBldmFsdWF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRRdWFsaXR5UmVjb21tZW5kYXRpb25zKFxuICByYWdFdmFsOiBSQUdFdmFsdWF0aW9uLFxuICBoYWxsdWNpbmF0aW9uUmVwb3J0PzogSGFsbHVjaW5hdGlvblJlcG9ydFxuKTogc3RyaW5nW10ge1xuICBjb25zdCByZWNvbW1lbmRhdGlvbnM6IHN0cmluZ1tdID0gW107XG5cbiAgaWYgKHJhZ0V2YWwuZ3JvdW5kZWRuZXNzIDwgMC43KSB7XG4gICAgcmVjb21tZW5kYXRpb25zLnB1c2goJ0ltcHJvdmUgZ3JvdW5kaW5nIGJ5IGluY3JlYXNpbmcgY29udGV4dCByZWxldmFuY2UnKTtcbiAgfVxuXG4gIGlmIChyYWdFdmFsLmNvbnRleHRSZWxldmFuY2UgPCAwLjYpIHtcbiAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnVHVuZSByZXRyaWV2YWwgdG8gcmV0dXJuIG1vcmUgcmVsZXZhbnQgY29udGV4dHMnKTtcbiAgfVxuXG4gIGlmIChyYWdFdmFsLmNpdGF0aW9uQWNjdXJhY3kgPCAwLjgpIHtcbiAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnSW1wcm92ZSBjaXRhdGlvbiBhY2N1cmFjeSBpbiByZXNwb25zZXMnKTtcbiAgfVxuXG4gIGlmIChoYWxsdWNpbmF0aW9uUmVwb3J0Py5oYXNIYWxsdWNpbmF0aW9ucykge1xuICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKCdBZGQgZmFjdC1jaGVja2luZyBsYXllciB0byByZWR1Y2UgaGFsbHVjaW5hdGlvbnMnKTtcbiAgfVxuXG4gIGlmIChyZWNvbW1lbmRhdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgcmVjb21tZW5kYXRpb25zLnB1c2goJ1F1YWxpdHkgbWV0cmljcyBhcmUgd2l0aGluIGFjY2VwdGFibGUgcmFuZ2VzJyk7XG4gIH1cblxuICByZXR1cm4gcmVjb21tZW5kYXRpb25zO1xufVxuXG4vKipcbiAqIEZvcm1hdCBxdWFsaXR5IHNjb3JlIGZvciBkaXNwbGF5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRRdWFsaXR5U2NvcmUoc2NvcmU6IG51bWJlcik6IHN0cmluZyB7XG4gIHJldHVybiBgJHtNYXRoLnJvdW5kKHNjb3JlICogMTAwKX0lYDtcbn1cblxuLyoqXG4gKiBHZXQgY29sb3IgaW5kaWNhdG9yIGZvciBncmFkZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0R3JhZGVDb2xvcihcbiAgZ3JhZGU6ICdBJyB8ICdCJyB8ICdDJyB8ICdEJyB8ICdGJ1xuKTogJ2dyZWVuJyB8ICdibHVlJyB8ICd5ZWxsb3cnIHwgJ29yYW5nZScgfCAncmVkJyB7XG4gIGNvbnN0IGNvbG9ycyA9IHtcbiAgICBBOiAnZ3JlZW4nIGFzIGNvbnN0LFxuICAgIEI6ICdibHVlJyBhcyBjb25zdCxcbiAgICBDOiAneWVsbG93JyBhcyBjb25zdCxcbiAgICBEOiAnb3JhbmdlJyBhcyBjb25zdCxcbiAgICBGOiAncmVkJyBhcyBjb25zdCxcbiAgfTtcbiAgcmV0dXJuIGNvbG9yc1tncmFkZV07XG59XG4iXX0=
|