@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,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ThinkHive SDK v3.0 - Conversation Evaluation API
|
|
4
|
+
*
|
|
5
|
+
* API for multi-turn conversation evaluation
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.conversationEval = void 0;
|
|
9
|
+
exports.aggregateWorst = aggregateWorst;
|
|
10
|
+
exports.aggregateAverage = aggregateAverage;
|
|
11
|
+
exports.aggregateWeighted = aggregateWeighted;
|
|
12
|
+
exports.aggregateFinalTurn = aggregateFinalTurn;
|
|
13
|
+
exports.aggregateMajority = aggregateMajority;
|
|
14
|
+
exports.getAggregator = getAggregator;
|
|
15
|
+
exports.getProblematicTurns = getProblematicTurns;
|
|
16
|
+
exports.analyzeConversationTrend = analyzeConversationTrend;
|
|
17
|
+
const client_1 = require("../core/client");
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// CONVERSATION EVAL API CLIENT
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/**
|
|
22
|
+
* Conversation Evaluation API client for multi-turn evaluation
|
|
23
|
+
*/
|
|
24
|
+
exports.conversationEval = {
|
|
25
|
+
/**
|
|
26
|
+
* Get traces for a conversation session
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const traces = await conversationEval.getSessionTraces('session_123');
|
|
31
|
+
* console.log(`Conversation has ${traces.length} turns`);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
async getSessionTraces(sessionId) {
|
|
35
|
+
return (0, client_1.apiRequestWithData)(`/conversation-eval/traces?sessionId=${sessionId}`, { apiVersion: 'v1' });
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Run conversation-level evaluation
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const result = await conversationEval.evaluate({
|
|
43
|
+
* sessionId: 'session_123',
|
|
44
|
+
* criterionId: 'criterion_456',
|
|
45
|
+
* options: {
|
|
46
|
+
* aggregateMethod: 'average',
|
|
47
|
+
* minTurns: 2,
|
|
48
|
+
* },
|
|
49
|
+
* });
|
|
50
|
+
* console.log(`Conversation score: ${result.aggregateScore}`);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
async evaluate(options) {
|
|
54
|
+
return (0, client_1.apiRequestWithData)('/conversation-eval/evaluate', {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
body: options,
|
|
57
|
+
apiVersion: 'v1',
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
/**
|
|
61
|
+
* Get available aggregation methods with descriptions
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const methods = await conversationEval.getAggregationMethods();
|
|
66
|
+
* for (const method of methods) {
|
|
67
|
+
* console.log(`${method.name}: ${method.description}`);
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
async getAggregationMethods() {
|
|
72
|
+
return (0, client_1.apiRequestWithData)('/conversation-eval/aggregation-methods', { apiVersion: 'v1' });
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// HELPER FUNCTIONS
|
|
77
|
+
// ============================================================================
|
|
78
|
+
/**
|
|
79
|
+
* Calculate worst-turn aggregation
|
|
80
|
+
*
|
|
81
|
+
* @param turnResults - Array of turn evaluation results
|
|
82
|
+
* @returns Aggregated result using worst turn logic
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const result = aggregateWorst(turnResults);
|
|
87
|
+
* // Fails if any turn fails
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
function aggregateWorst(turnResults) {
|
|
91
|
+
if (turnResults.length === 0)
|
|
92
|
+
return { passed: false, score: 0 };
|
|
93
|
+
const worstScore = Math.min(...turnResults.map(t => t.score));
|
|
94
|
+
const passed = turnResults.every(t => t.passed);
|
|
95
|
+
return { passed, score: worstScore };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Calculate average aggregation
|
|
99
|
+
*
|
|
100
|
+
* @param turnResults - Array of turn evaluation results
|
|
101
|
+
* @returns Aggregated result using average logic
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const result = aggregateAverage(turnResults);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
function aggregateAverage(turnResults) {
|
|
109
|
+
if (turnResults.length === 0)
|
|
110
|
+
return { passed: false, score: 0 };
|
|
111
|
+
const avgScore = turnResults.reduce((sum, t) => sum + t.score, 0) / turnResults.length;
|
|
112
|
+
const passedCount = turnResults.filter(t => t.passed).length;
|
|
113
|
+
const passed = passedCount > turnResults.length / 2;
|
|
114
|
+
return { passed, score: avgScore };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Calculate weighted average aggregation (later turns weighted more)
|
|
118
|
+
*
|
|
119
|
+
* @param turnResults - Array of turn evaluation results
|
|
120
|
+
* @returns Aggregated result using weighted average logic
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const result = aggregateWeighted(turnResults);
|
|
125
|
+
* // Later turns have higher weight
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
function aggregateWeighted(turnResults) {
|
|
129
|
+
if (turnResults.length === 0)
|
|
130
|
+
return { passed: false, score: 0 };
|
|
131
|
+
// Linear weights: 1, 2, 3, ...
|
|
132
|
+
let weightedSum = 0;
|
|
133
|
+
let weightTotal = 0;
|
|
134
|
+
let weightedPassSum = 0;
|
|
135
|
+
turnResults.forEach((turn, index) => {
|
|
136
|
+
const weight = index + 1;
|
|
137
|
+
weightedSum += turn.score * weight;
|
|
138
|
+
weightedPassSum += (turn.passed ? 1 : 0) * weight;
|
|
139
|
+
weightTotal += weight;
|
|
140
|
+
});
|
|
141
|
+
const avgScore = weightedSum / weightTotal;
|
|
142
|
+
const passed = (weightedPassSum / weightTotal) > 0.5;
|
|
143
|
+
return { passed, score: avgScore };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Calculate final-turn aggregation
|
|
147
|
+
*
|
|
148
|
+
* @param turnResults - Array of turn evaluation results
|
|
149
|
+
* @returns Aggregated result using only the final turn
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const result = aggregateFinalTurn(turnResults);
|
|
154
|
+
* // Only final turn matters
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
function aggregateFinalTurn(turnResults) {
|
|
158
|
+
if (turnResults.length === 0)
|
|
159
|
+
return { passed: false, score: 0 };
|
|
160
|
+
const finalTurn = turnResults[turnResults.length - 1];
|
|
161
|
+
return { passed: finalTurn.passed, score: finalTurn.score };
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Calculate majority vote aggregation
|
|
165
|
+
*
|
|
166
|
+
* @param turnResults - Array of turn evaluation results
|
|
167
|
+
* @returns Aggregated result using majority vote logic
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const result = aggregateMajority(turnResults);
|
|
172
|
+
* // Passes if majority of turns pass
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
function aggregateMajority(turnResults) {
|
|
176
|
+
if (turnResults.length === 0)
|
|
177
|
+
return { passed: false, score: 0 };
|
|
178
|
+
const passedCount = turnResults.filter(t => t.passed).length;
|
|
179
|
+
const passed = passedCount > turnResults.length / 2;
|
|
180
|
+
const avgScore = turnResults.reduce((sum, t) => sum + t.score, 0) / turnResults.length;
|
|
181
|
+
return { passed, score: avgScore };
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get appropriate aggregation function for a method
|
|
185
|
+
*
|
|
186
|
+
* @param method - Aggregation method name
|
|
187
|
+
* @returns Aggregation function
|
|
188
|
+
*/
|
|
189
|
+
function getAggregator(method) {
|
|
190
|
+
switch (method) {
|
|
191
|
+
case 'worst': return aggregateWorst;
|
|
192
|
+
case 'average': return aggregateAverage;
|
|
193
|
+
case 'weighted': return aggregateWeighted;
|
|
194
|
+
case 'final_turn': return aggregateFinalTurn;
|
|
195
|
+
case 'majority': return aggregateMajority;
|
|
196
|
+
default: return aggregateAverage;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Find problematic turns in a conversation
|
|
201
|
+
*
|
|
202
|
+
* @param result - Conversation evaluation result
|
|
203
|
+
* @param scoreThreshold - Minimum acceptable score (default 70)
|
|
204
|
+
* @returns Array of problematic turn results
|
|
205
|
+
*/
|
|
206
|
+
function getProblematicTurns(result, scoreThreshold = 70) {
|
|
207
|
+
return result.turnResults.filter(t => !t.passed || t.score < scoreThreshold);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Calculate conversation quality trend
|
|
211
|
+
*
|
|
212
|
+
* @param result - Conversation evaluation result
|
|
213
|
+
* @returns Trend analysis
|
|
214
|
+
*/
|
|
215
|
+
function analyzeConversationTrend(result) {
|
|
216
|
+
const turns = result.turnResults;
|
|
217
|
+
if (turns.length < 2) {
|
|
218
|
+
return { direction: 'stable', firstHalfAvg: 0, secondHalfAvg: 0 };
|
|
219
|
+
}
|
|
220
|
+
const midpoint = Math.floor(turns.length / 2);
|
|
221
|
+
const firstHalf = turns.slice(0, midpoint);
|
|
222
|
+
const secondHalf = turns.slice(midpoint);
|
|
223
|
+
const firstHalfAvg = firstHalf.reduce((sum, t) => sum + t.score, 0) / firstHalf.length;
|
|
224
|
+
const secondHalfAvg = secondHalf.reduce((sum, t) => sum + t.score, 0) / secondHalf.length;
|
|
225
|
+
const diff = secondHalfAvg - firstHalfAvg;
|
|
226
|
+
let direction;
|
|
227
|
+
if (diff > 5)
|
|
228
|
+
direction = 'improving';
|
|
229
|
+
else if (diff < -5)
|
|
230
|
+
direction = 'declining';
|
|
231
|
+
else
|
|
232
|
+
direction = 'stable';
|
|
233
|
+
return { direction, firstHalfAvg, secondHalfAvg };
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udmVyc2F0aW9uLWV2YWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL2NvbnZlcnNhdGlvbi1ldmFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7OztHQUlHOzs7QUE0SUgsd0NBT0M7QUFhRCw0Q0FRQztBQWNELDhDQW1CQztBQWNELGdEQUtDO0FBY0QsOENBUUM7QUFRRCxzQ0FXQztBQVNELGtEQUtDO0FBUUQsNERBeUJDO0FBbFRELDJDQUFvRDtBQXVEcEQsK0VBQStFO0FBQy9FLCtCQUErQjtBQUMvQiwrRUFBK0U7QUFFL0U7O0dBRUc7QUFDVSxRQUFBLGdCQUFnQixHQUFHO0lBQzlCOzs7Ozs7OztPQVFHO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUFDLFNBQWlCO1FBQ3RDLE9BQU8sSUFBQSwyQkFBa0IsRUFDdkIsdUNBQXVDLFNBQVMsRUFBRSxFQUNsRCxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FDckIsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7O09BZUc7SUFDSCxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQW9DO1FBQ2pELE9BQU8sSUFBQSwyQkFBa0IsRUFBeUIsNkJBQTZCLEVBQUU7WUFDL0UsTUFBTSxFQUFFLE1BQU07WUFDZCxJQUFJLEVBQUUsT0FBTztZQUNiLFVBQVUsRUFBRSxJQUFJO1NBQ2pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHO0lBQ0gsS0FBSyxDQUFDLHFCQUFxQjtRQUN6QixPQUFPLElBQUEsMkJBQWtCLEVBQ3ZCLHdDQUF3QyxFQUN4QyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FDckIsQ0FBQztJQUNKLENBQUM7Q0FDRixDQUFDO0FBRUYsK0VBQStFO0FBQy9FLG1CQUFtQjtBQUNuQiwrRUFBK0U7QUFFL0U7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxTQUFnQixjQUFjLENBQUMsV0FBNkI7SUFDMUQsSUFBSSxXQUFXLENB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QU0sSUFBSSxHQUFHLGFBQWEsR0FBRyxZQUFZLENBQUM7SUFDMUMsSUFBSSxTQUErQyxDQUFDO0lBRXBELElBQUksSUFBSSxHQUFHLENBQUM7UUFBRSxTQUFTLEdBQUcsV0FBVyxDQUFDO1NBQ2pDLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQztRQUFFLFNBQVMsR0FBRyxXQUFXLENBQUM7O1FBQ3ZDLFNBQVMsR0FBRyxRQUFRLENBQUM7SUFFMUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLENBQUM7QUFDcEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhpbmtIaXZlIFNESyB2My4wIC0gQ29udmVyc2F0aW9uIEV2YWx1YXRpb24gQVBJXG4gKlxuICogQVBJIGZvciBtdWx0aS10dXJuIGNvbnZlcnNhdGlvbiBldmFsdWF0aW9uXG4gKi9cblxuaW1wb3J0IHsgYXBpUmVxdWVzdFdpdGhEYXRhIH0gZnJvbSAnLi4vY29yZS9jbGllbnQnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgdHlwZSBBZ2dyZWdhdGVNZXRob2QgPSAnd29yc3QnIHwgJ2F2ZXJhZ2UnIHwgJ3dlaWdodGVkJyB8ICdmaW5hbF90dXJuJyB8ICdtYWpvcml0eSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2Vzc2lvblRyYWNlIHtcbiAgaWQ6IHN0cmluZztcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIHR1cm5OdW1iZXI6IG51bWJlcjtcbiAgdXNlck1lc3NhZ2U6IHN0cmluZztcbiAgYWdlbnRSZXNwb25zZTogc3RyaW5nO1xuICB0aW1lc3RhbXA6IHN0cmluZztcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUdXJuRXZhbHVhdGlvbiB7XG4gIHRyYWNlSWQ6IHN0cmluZztcbiAgdHVybk51bWJlcjogbnVtYmVyO1xuICBwYXNzZWQ6IGJvb2xlYW47XG4gIHNjb3JlOiBudW1iZXI7XG4gIHJlYXNvbmluZzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnZlcnNhdGlvbkV2YWxSZXN1bHQge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgY3JpdGVyaW9uSWQ6IHN0cmluZztcbiAgdHVybkNvdW50OiBudW1iZXI7XG4gIHR1cm5SZXN1bHRzOiBUdXJuRXZhbHVhdGlvbltdO1xuICBhZ2dyZWdhdGVQYXNzZWQ6IGJvb2xlYW47XG4gIGFnZ3JlZ2F0ZVNjb3JlOiBudW1iZXI7XG4gIGFnZ3JlZ2F0ZU1ldGhvZDogQWdncmVnYXRlTWV0aG9kO1xuICByZWFzb25pbmc6IHN0cmluZztcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFdmFsdWF0ZUNvbnZlcnNhdGlvbk9wdGlvbnMge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgY3JpdGVyaW9uSWQ6IHN0cmluZztcbiAgb3B0aW9ucz86IHtcbiAgICBhZ2dyZWdhdGVNZXRob2Q/OiBBZ2dyZWdhdGVNZXRob2Q7XG4gICAgbWluVHVybnM/OiBudW1iZXI7XG4gICAgbWF4VHVybnM/OiBudW1iZXI7XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWdncmVnYXRpb25NZXRob2RJbmZvIHtcbiAgaWQ6IEFnZ3JlZ2F0ZU1ldGhvZDtcbiAgbmFtZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICB1c2VDYXNlOiBzdHJpbmc7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIENPTlZFUlNBVElPTiBFVkFMIEFQSSBDTElFTlRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDb252ZXJzYXRpb24gRXZhbHVhdGlvbiBBUEkgY2xpZW50IGZvciBtdWx0aS10dXJuIGV2YWx1YXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IGNvbnZlcnNhdGlvbkV2YWwgPSB7XG4gIC8qKlxuICAgKiBHZXQgdHJhY2VzIGZvciBhIGNvbnZlcnNhdGlvbiBzZXNzaW9uXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdHJhY2VzID0gYXdhaXQgY29udmVyc2F0aW9uRXZhbC5nZXRTZXNzaW9uVHJhY2VzKCdzZXNzaW9uXzEyMycpO1xuICAgKiBjb25zb2xlLmxvZyhgQ29udmVyc2F0aW9uIGhhcyAke3RyYWNlcy5sZW5ndGh9IHR1cm5zYCk7XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgZ2V0U2Vzc2lvblRyYWNlcyhzZXNzaW9uSWQ6IHN0cmluZyk6IFByb21pc2U8U2Vzc2lvblRyYWNlW10+IHtcbiAgICByZXR1cm4gYXBpUmVxdWVzdFdpdGhEYXRhPFNlc3Npb25UcmFjZVtdPihcbiAgICAgIGAvY29udmVyc2F0aW9uLWV2YWwvdHJhY2VzP3Nlc3Npb25JZD0ke3Nlc3Npb25JZH1gLFxuICAgICAgeyBhcGlWZXJzaW9uOiAndjEnIH1cbiAgICApO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSdW4gY29udmVyc2F0aW9uLWxldmVsIGV2YWx1YXRpb25cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJzYXRpb25FdmFsLmV2YWx1YXRlKHtcbiAgICogICBzZXNzaW9uSWQ6ICdzZXNzaW9uXzEyMycsXG4gICAqICAgY3JpdGVyaW9uSWQ6ICdjcml0ZXJpb25fNDU2JyxcbiAgICogICBvcHRpb25zOiB7XG4gICAqICAgICBhZ2dyZWdhdGVNZXRob2Q6ICdhdmVyYWdlJyxcbiAgICogICAgIG1pblR1cm5zOiAyLFxuICAgKiAgIH0sXG4gICAqIH0pO1xuICAgKiBjb25zb2xlLmxvZyhgQ29udmVyc2F0aW9uIHNjb3JlOiAke3Jlc3VsdC5hZ2dyZWdhdGVTY29yZX1gKTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBldmFsdWF0ZShvcHRpb25zOiBFdmFsdWF0ZUNvbnZlcnNhdGlvbk9wdGlvbnMpOiBQcm9taXNlPENvbnZlcnNhdGlvbkV2YWxSZXN1bHQ+IHtcbiAgICByZXR1cm4gYXBpUmVxdWVzdFdpdGhEYXRhPENvbnZlcnNhdGlvbkV2YWxSZXN1bHQ+KCcvY29udmVyc2F0aW9uLWV2YWwvZXZhbHVhdGUnLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgICBhcGlWZXJzaW9uOiAndjEnLFxuICAgIH0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZXQgYXZhaWxhYmxlIGFnZ3JlZ2F0aW9uIG1ldGhvZHMgd2l0aCBkZXNjcmlwdGlvbnNcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBtZXRob2RzID0gYXdhaXQgY29udmVyc2F0aW9uRXZhbC5nZXRBZ2dyZWdhdGlvbk1ldGhvZHMoKTtcbiAgICogZm9yIChjb25zdCBtZXRob2Qgb2YgbWV0aG9kcykge1xuICAgKiAgIGNvbnNvbGUubG9nKGAke21ldGhvZC5uYW1lfTogJHttZXRob2QuZGVzY3JpcHRpb259YCk7XG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBnZXRBZ2dyZWdhdGlvbk1ldGhvZHMoKTogUHJvbWlzZTxBZ2dyZWdhdGlvbk1ldGhvZEluZm9bXT4ge1xuICAgIHJldHVybiBhcGlSZXF1ZXN0V2l0aERhdGE8QWdncmVnYXRpb25NZXRob2RJbmZvW10+KFxuICAgICAgJy9jb252ZXJzYXRpb24tZXZhbC9hZ2dyZWdhdGlvbi1tZXRob2RzJyxcbiAgICAgIHsgYXBpVmVyc2lvbjogJ3YxJyB9XG4gICAgKTtcbiAgfSxcbn07XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDYWxjdWxhdGUgd29yc3QtdHVybiBhZ2dyZWdhdGlvblxuICpcbiAqIEBwYXJhbSB0dXJuUmVzdWx0cyAtIEFycmF5IG9mIHR1cm4gZXZhbHVhdGlvbiByZXN1bHRzXG4gKiBAcmV0dXJucyBBZ2dyZWdhdGVkIHJlc3VsdCB1c2luZyB3b3JzdCB0dXJuIGxvZ2ljXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHJlc3VsdCA9IGFnZ3JlZ2F0ZVdvcnN0KHR1cm5SZXN1bHRzKTtcbiAqIC8vIEZhaWxzIGlmIGFueSB0dXJuIGZhaWxzXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFnZ3JlZ2F0ZVdvcnN0KHR1cm5SZXN1bHRzOiBUdXJuRXZhbHVhdGlvbltdKTogeyBwYXNzZWQ6IGJvb2xlYW47IHNjb3JlOiBudW1iZXIgfSB7XG4gIGlmICh0dXJuUmVzdWx0cy5sZW5ndGggPT09IDApIHJldHVybiB7IHBhc3NlZDogZmFsc2UsIHNjb3JlOiAwIH07XG5cbiAgY29uc3Qgd29yc3RTY29yZSA9IE1hdGgubWluKC4uLnR1cm5SZXN1bHRzLm1hcCh0ID0+IHQuc2NvcmUpKTtcbiAgY29uc3QgcGFzc2VkID0gdHVyblJlc3VsdHMuZXZlcnkodCA9PiB0LnBhc3NlZCk7XG5cbiAgcmV0dXJuIHsgcGFzc2VkLCBzY29yZTogd29yc3RTY29yZSB9O1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZSBhdmVyYWdlIGFnZ3JlZ2F0aW9uXG4gKlxuICogQHBhcmFtIHR1cm5SZXN1bHRzIC0gQXJyYXkgb2YgdHVybiBldmFsdWF0aW9uIHJlc3VsdHNcbiAqIEByZXR1cm5zIEFnZ3JlZ2F0ZWQgcmVzdWx0IHVzaW5nIGF2ZXJhZ2UgbG9naWNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcmVzdWx0ID0gYWdncmVnYXRlQXZlcmFnZSh0dXJuUmVzdWx0cyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFnZ3JlZ2F0ZUF2ZXJhZ2UodHVyblJlc3VsdHM6IFR1cm5FdmFsdWF0aW9uW10pOiB7IHBhc3NlZDogYm9vbGVhbjsgc2NvcmU6IG51bWJlciB9IHtcbiAgaWYgKHR1cm5SZXN1bHRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHsgcGFzc2VkOiBmYWxzZSwgc2NvcmU6IDAgfTtcblxuICBjb25zdCBhdmdTY29yZSA9IHR1cm5SZXN1bHRzLnJlZHVjZSgoc3VtLCB0KSA9PiBzdW0gKyB0LnNjb3JlLCAwKSAvIHR1cm5SZXN1bHRzLmxlbmd0aDtcbiAgY29uc3QgcGFzc2VkQ291bnQgPSB0dXJuUmVzdWx0cy5maWx0ZXIodCA9PiB0LnBhc3NlZCkubGVuZ3RoO1xuICBjb25zdCBwYXNzZWQgPSBwYXNzZWRDb3VudCA+IHR1cm5SZXN1bHRzLmxlbmd0aCAvIDI7XG5cbiAgcmV0dXJuIHsgcGFzc2VkLCBzY29yZTogYXZnU2NvcmUgfTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgd2VpZ2h0ZWQgYXZlcmFnZSBhZ2dyZWdhdGlvbiAobGF0ZXIgdHVybnMgd2VpZ2h0ZWQgbW9yZSlcbiAqXG4gKiBAcGFyYW0gdHVyblJlc3VsdHMgLSBBcnJheSBvZiB0dXJuIGV2YWx1YXRpb24gcmVzdWx0c1xuICogQHJldHVybnMgQWdncmVnYXRlZCByZXN1bHQgdXNpbmcgd2VpZ2h0ZWQgYXZlcmFnZSBsb2dpY1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCByZXN1bHQgPSBhZ2dyZWdhdGVXZWlnaHRlZCh0dXJuUmVzdWx0cyk7XG4gKiAvLyBMYXRlciB0dXJucyBoYXZlIGhpZ2hlciB3ZWlnaHRcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWdncmVnYXRlV2VpZ2h0ZWQodHVyblJlc3VsdHM6IFR1cm5FdmFsdWF0aW9uW10pOiB7IHBhc3NlZDogYm9vbGVhbjsgc2NvcmU6IG51bWJlciB9IHtcbiAgaWYgKHR1cm5SZXN1bHRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHsgcGFzc2VkOiBmYWxzZSwgc2NvcmU6IDAgfTtcblxuICAvLyBMaW5lYXIgd2VpZ2h0czogMSwgMiwgMywgLi4uXG4gIGxldCB3ZWlnaHRlZFN1bSA9IDA7XG4gIGxldCB3ZWlnaHRUb3RhbCA9IDA7XG4gIGxldCB3ZWlnaHRlZFBhc3NTdW0gPSAwO1xuXG4gIHR1cm5SZXN1bHRzLmZvckVhY2goKHR1cm4sIGluZGV4KSA9PiB7XG4gICAgY29uc3Qgd2VpZ2h0ID0gaW5kZXggKyAxO1xuICAgIHdlaWdodGVkU3VtICs9IHR1cm4uc2NvcmUgKiB3ZWlnaHQ7XG4gICAgd2VpZ2h0ZWRQYXNzU3VtICs9ICh0dXJuLnBhc3NlZCA/IDEgOiAwKSAqIHdlaWdodDtcbiAgICB3ZWlnaHRUb3RhbCArPSB3ZWlnaHQ7XG4gIH0pO1xuXG4gIGNvbnN0IGF2Z1Njb3JlID0gd2VpZ2h0ZWRTdW0gLyB3ZWlnaHRUb3RhbDtcbiAgY29uc3QgcGFzc2VkID0gKHdlaWdodGVkUGFzc1N1bSAvIHdlaWdodFRvdGFsKSA+IDAuNTtcblxuICByZXR1cm4geyBwYXNzZWQsIHNjb3JlOiBhdmdTY29yZSB9O1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZSBmaW5hbC10dXJuIGFnZ3JlZ2F0aW9uXG4gKlxuICogQHBhcmFtIHR1cm5SZXN1bHRzIC0gQXJyYXkgb2YgdHVybiBldmFsdWF0aW9uIHJlc3VsdHNcbiAqIEByZXR1cm5zIEFnZ3JlZ2F0ZWQgcmVzdWx0IHVzaW5nIG9ubHkgdGhlIGZpbmFsIHR1cm5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcmVzdWx0ID0gYWdncmVnYXRlRmluYWxUdXJuKHR1cm5SZXN1bHRzKTtcbiAqIC8vIE9ubHkgZmluYWwgdHVybiBtYXR0ZXJzXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFnZ3JlZ2F0ZUZpbmFsVHVybih0dXJuUmVzdWx0czogVHVybkV2YWx1YXRpb25bXSk6IHsgcGFzc2VkOiBib29sZWFuOyBzY29yZTogbnVtYmVyIH0ge1xuICBpZiAodHVyblJlc3VsdHMubGVuZ3RoID09PSAwKSByZXR1cm4geyBwYXNzZWQ6IGZhbHNlLCBzY29yZTogMCB9O1xuXG4gIGNvbnN0IGZpbmFsVHVybiA9IHR1cm5SZXN1bHRzW3R1cm5SZXN1bHRzLmxlbmd0aCAtIDFdO1xuICByZXR1cm4geyBwYXNzZWQ6IGZpbmFsVHVybi5wYXNzZWQsIHNjb3JlOiBmaW5hbFR1cm4uc2NvcmUgfTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgbWFqb3JpdHkgdm90ZSBhZ2dyZWdhdGlvblxuICpcbiAqIEBwYXJhbSB0dXJuUmVzdWx0cyAtIEFycmF5IG9mIHR1cm4gZXZhbHVhdGlvbiByZXN1bHRzXG4gKiBAcmV0dXJucyBBZ2dyZWdhdGVkIHJlc3VsdCB1c2luZyBtYWpvcml0eSB2b3RlIGxvZ2ljXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHJlc3VsdCA9IGFnZ3JlZ2F0ZU1ham9yaXR5KHR1cm5SZXN1bHRzKTtcbiAqIC8vIFBhc3NlcyBpZiBtYWpvcml0eSBvZiB0dXJucyBwYXNzXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFnZ3JlZ2F0ZU1ham9yaXR5KHR1cm5SZXN1bHRzOiBUdXJuRXZhbHVhdGlvbltdKTogeyBwYXNzZWQ6IGJvb2xlYW47IHNjb3JlOiBudW1iZXIgfSB7XG4gIGlmICh0dXJuUmVzdWx0cy5sZW5ndGggPT09IDApIHJldHVybiB7IHBhc3NlZDogZmFsc2UsIHNjb3JlOiAwIH07XG5cbiAgY29uc3QgcGFzc2VkQ291bnQgPSB0dXJuUmVzdWx0cy5maWx0ZXIodCA9PiB0LnBhc3NlZCkubGVuZ3RoO1xuICBjb25zdCBwYXNzZWQgPSBwYXNzZWRDb3VudCA+IHR1cm5SZXN1bHRzLmxlbmd0aCAvIDI7XG4gIGNvbnN0IGF2Z1Njb3JlID0gdHVyblJlc3VsdHMucmVkdWNlKChzdW0sIHQpID0+IHN1bSArIHQuc2NvcmUsIDApIC8gdHVyblJlc3VsdHMubGVuZ3RoO1xuXG4gIHJldHVybiB7IHBhc3NlZCwgc2NvcmU6IGF2Z1Njb3JlIH07XG59XG5cbi8qKlxuICogR2V0IGFwcHJvcHJpYXRlIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9uIGZvciBhIG1ldGhvZFxuICpcbiAqIEBwYXJhbSBtZXRob2QgLSBBZ2dyZWdhdGlvbiBtZXRob2QgbmFtZVxuICogQHJldHVybnMgQWdncmVnYXRpb24gZnVuY3Rpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFnZ3JlZ2F0b3IoXG4gIG1ldGhvZDogQWdncmVnYXRlTWV0aG9kXG4pOiAodHVyblJlc3VsdHM6IFR1cm5FdmFsdWF0aW9uW10pID0+IHsgcGFzc2VkOiBib29sZWFuOyBzY29yZTogbnVtYmVyIH0ge1xuICBzd2l0Y2ggKG1ldGhvZCkge1xuICAgIGNhc2UgJ3dvcnN0JzogcmV0dXJuIGFnZ3JlZ2F0ZVdvcnN0O1xuICAgIGNhc2UgJ2F2ZXJhZ2UnOiByZXR1cm4gYWdncmVnYXRlQXZlcmFnZTtcbiAgICBjYXNlICd3ZWlnaHRlZCc6IHJldHVybiBhZ2dyZWdhdGVXZWlnaHRlZDtcbiAgICBjYXNlICdmaW5hbF90dXJuJzogcmV0dXJuIGFnZ3JlZ2F0ZUZpbmFsVHVybjtcbiAgICBjYXNlICdtYWpvcml0eSc6IHJldHVybiBhZ2dyZWdhdGVNYWpvcml0eTtcbiAgICBkZWZhdWx0OiByZXR1cm4gYWdncmVnYXRlQXZlcmFnZTtcbiAgfVxufVxuXG4vKipcbiAqIEZpbmQgcHJvYmxlbWF0aWMgdHVybnMgaW4gYSBjb252ZXJzYXRpb25cbiAqXG4gKiBAcGFyYW0gcmVzdWx0IC0gQ29udmVyc2F0aW9uIGV2YWx1YXRpb24gcmVzdWx0XG4gKiBAcGFyYW0gc2NvcmVUaHJlc2hvbGQgLSBNaW5pbXVtIGFjY2VwdGFibGUgc2NvcmUgKGRlZmF1bHQgNzApXG4gKiBAcmV0dXJucyBBcnJheSBvZiBwcm9ibGVtYXRpYyB0dXJuIHJlc3VsdHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFByb2JsZW1hdGljVHVybnMoXG4gIHJlc3VsdDogQ29udmVyc2F0aW9uRXZhbFJlc3VsdCxcbiAgc2NvcmVUaHJlc2hvbGQgPSA3MFxuKTogVHVybkV2YWx1YXRpb25bXSB7XG4gIHJldHVybiByZXN1bHQudHVyblJlc3VsdHMuZmlsdGVyKHQgPT4gIXQucGFzc2VkIHx8IHQuc2NvcmUgPCBzY29yZVRocmVzaG9sZCk7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIGNvbnZlcnNhdGlvbiBxdWFsaXR5IHRyZW5kXG4gKlxuICogQHBhcmFtIHJlc3VsdCAtIENvbnZlcnNhdGlvbiBldmFsdWF0aW9uIHJlc3VsdFxuICogQHJldHVybnMgVHJlbmQgYW5hbHlzaXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFuYWx5emVDb252ZXJzYXRpb25UcmVuZChyZXN1bHQ6IENvbnZlcnNhdGlvbkV2YWxSZXN1bHQpOiB7XG4gIGRpcmVjdGlvbjogJ2ltcHJvdmluZycgfCAnZGVjbGluaW5nJyB8ICdzdGFibGUnO1xuICBmaXJzdEhhbGZBdmc6IG51bWJlcjtcbiAgc2Vjb25kSGFsZkF2ZzogbnVtYmVyO1xufSB7XG4gIGNvbnN0IHR1cm5zID0gcmVzdWx0LnR1cm5SZXN1bHRzO1xuICBpZiAodHVybnMubGVuZ3RoIDwgMikge1xuICAgIHJldHVybiB7IGRpcmVjdGlvbjogJ3N0YWJsZScsIGZpcnN0SGFsZkF2ZzogMCwgc2Vjb25kSGFsZkF2ZzogMCB9O1xuICB9XG5cbiAgY29uc3QgbWlkcG9pbnQgPSBNYXRoLmZsb29yKHR1cm5zLmxlbmd0aCAvIDIpO1xuICBjb25zdCBmaXJzdEhhbGYgPSB0dXJucy5zbGljZSgwLCBtaWRwb2ludCk7XG4gIGNvbnN0IHNlY29uZEhhbGYgPSB0dXJucy5zbGljZShtaWRwb2ludCk7XG5cbiAgY29uc3QgZmlyc3RIYWxmQXZnID0gZmlyc3RIYWxmLnJlZHVjZSgoc3VtLCB0KSA9PiBzdW0gKyB0LnNjb3JlLCAwKSAvIGZpcnN0SGFsZi5sZW5ndGg7XG4gIGNvbnN0IHNlY29uZEhhbGZBdmcgPSBzZWNvbmRIYWxmLnJlZHVjZSgoc3VtLCB0KSA9PiBzdW0gKyB0LnNjb3JlLCAwKSAvIHNlY29uZEhhbGYubGVuZ3RoO1xuXG4gIGNvbnN0IGRpZmYgPSBzZWNvbmRIYWxmQXZnIC0gZmlyc3RIYWxmQXZnO1xuICBsZXQgZGlyZWN0aW9uOiAnaW1wcm92aW5nJyB8ICdkZWNsaW5pbmcnIHwgJ3N0YWJsZSc7XG5cbiAgaWYgKGRpZmYgPiA1KSBkaXJlY3Rpb24gPSAnaW1wcm92aW5nJztcbiAgZWxzZSBpZiAoZGlmZiA8IC01KSBkaXJlY3Rpb24gPSAnZGVjbGluaW5nJztcbiAgZWxzZSBkaXJlY3Rpb24gPSAnc3RhYmxlJztcblxuICByZXR1cm4geyBkaXJlY3Rpb24sIGZpcnN0SGFsZkF2Zywgc2Vjb25kSGFsZkF2ZyB9O1xufVxuIl19
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThinkHive SDK v3.0 - Deterministic Graders API
|
|
3
|
+
*
|
|
4
|
+
* API for running deterministic (code-based) evaluations
|
|
5
|
+
*/
|
|
6
|
+
export type RuleType = 'regex' | 'contains' | 'not_contains' | 'json_valid' | 'json_schema' | 'length' | 'pii_check' | 'sentiment' | 'latency' | 'token_count';
|
|
7
|
+
export interface DeterministicEvalResult {
|
|
8
|
+
passed: boolean;
|
|
9
|
+
score: number;
|
|
10
|
+
reasoning: string;
|
|
11
|
+
ruleResults?: RuleResult[];
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export interface RuleResult {
|
|
15
|
+
ruleId: string;
|
|
16
|
+
ruleName: string;
|
|
17
|
+
ruleType: RuleType;
|
|
18
|
+
passed: boolean;
|
|
19
|
+
score: number;
|
|
20
|
+
details?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface EvaluateOptions {
|
|
23
|
+
traceId: string;
|
|
24
|
+
criterionId: string;
|
|
25
|
+
}
|
|
26
|
+
export interface BulkEvaluateOptions {
|
|
27
|
+
evaluations: Array<{
|
|
28
|
+
traceId: string;
|
|
29
|
+
criterionId: string;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
export interface BulkEvaluateResult {
|
|
33
|
+
results: Array<{
|
|
34
|
+
traceId: string;
|
|
35
|
+
criterionId: string;
|
|
36
|
+
passed: boolean;
|
|
37
|
+
score: number;
|
|
38
|
+
error?: string;
|
|
39
|
+
}>;
|
|
40
|
+
summary: {
|
|
41
|
+
total: number;
|
|
42
|
+
passed: number;
|
|
43
|
+
failed: number;
|
|
44
|
+
passRate: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export interface RuleTypeInfo {
|
|
48
|
+
id: RuleType;
|
|
49
|
+
name: string;
|
|
50
|
+
description: string;
|
|
51
|
+
configFields: string[];
|
|
52
|
+
}
|
|
53
|
+
export interface RuleTemplate {
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
description: string;
|
|
57
|
+
ruleType: RuleType;
|
|
58
|
+
config: Record<string, unknown>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Deterministic Graders API client for code-based evaluations
|
|
62
|
+
*/
|
|
63
|
+
export declare const deterministicGraders: {
|
|
64
|
+
/**
|
|
65
|
+
* Run deterministic evaluation on a single trace
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const result = await deterministicGraders.evaluate({
|
|
70
|
+
* traceId: 'trace_123',
|
|
71
|
+
* criterionId: 'criterion_456',
|
|
72
|
+
* });
|
|
73
|
+
* console.log(`Passed: ${result.passed}, Score: ${result.score}`);
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
evaluate(options: EvaluateOptions): Promise<DeterministicEvalResult>;
|
|
77
|
+
/**
|
|
78
|
+
* Run deterministic evaluations on multiple traces
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const { results, summary } = await deterministicGraders.bulkEvaluate({
|
|
83
|
+
* evaluations: [
|
|
84
|
+
* { traceId: 'trace_1', criterionId: 'criterion_456' },
|
|
85
|
+
* { traceId: 'trace_2', criterionId: 'criterion_456' },
|
|
86
|
+
* { traceId: 'trace_3', criterionId: 'criterion_456' },
|
|
87
|
+
* ],
|
|
88
|
+
* });
|
|
89
|
+
* console.log(`Pass rate: ${summary.passRate * 100}%`);
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
bulkEvaluate(options: BulkEvaluateOptions): Promise<BulkEvaluateResult>;
|
|
93
|
+
/**
|
|
94
|
+
* Get available rule types with descriptions
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const ruleTypes = await deterministicGraders.getRuleTypes();
|
|
99
|
+
* for (const type of ruleTypes) {
|
|
100
|
+
* console.log(`${type.name}: ${type.description}`);
|
|
101
|
+
* }
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
getRuleTypes(): Promise<RuleTypeInfo[]>;
|
|
105
|
+
/**
|
|
106
|
+
* Get rule templates
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const templates = await deterministicGraders.getTemplates();
|
|
111
|
+
* const noPiiTemplate = templates.find(t => t.id === 'no_pii');
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
getTemplates(): Promise<RuleTemplate[]>;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Create a regex rule configuration
|
|
118
|
+
*
|
|
119
|
+
* @param pattern - Regular expression pattern
|
|
120
|
+
* @param flags - Regex flags (default: 'gi')
|
|
121
|
+
* @returns Rule configuration object
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* const config = createRegexRule('\\b(error|fail)\\b', 'gi');
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export declare function createRegexRule(pattern: string, flags?: string): {
|
|
129
|
+
pattern: string;
|
|
130
|
+
flags: string;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Create a contains rule configuration
|
|
134
|
+
*
|
|
135
|
+
* @param values - Strings to check for
|
|
136
|
+
* @param caseSensitive - Whether comparison is case-sensitive
|
|
137
|
+
* @returns Rule configuration object
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* const config = createContainsRule(['hello', 'hi', 'hey'], false);
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export declare function createContainsRule(values: string[], caseSensitive?: boolean): {
|
|
145
|
+
values: string[];
|
|
146
|
+
caseSensitive: boolean;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Create a length rule configuration
|
|
150
|
+
*
|
|
151
|
+
* @param min - Minimum length (optional)
|
|
152
|
+
* @param max - Maximum length (optional)
|
|
153
|
+
* @returns Rule configuration object
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const config = createLengthRule(50, 1000);
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export declare function createLengthRule(min?: number, max?: number): {
|
|
161
|
+
min?: number;
|
|
162
|
+
max?: number;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Create a JSON schema rule configuration
|
|
166
|
+
*
|
|
167
|
+
* @param schema - JSON Schema object
|
|
168
|
+
* @returns Rule configuration object
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* const config = createJsonSchemaRule({
|
|
173
|
+
* type: 'object',
|
|
174
|
+
* required: ['name', 'email'],
|
|
175
|
+
* properties: {
|
|
176
|
+
* name: { type: 'string' },
|
|
177
|
+
* email: { type: 'string', format: 'email' },
|
|
178
|
+
* },
|
|
179
|
+
* });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export declare function createJsonSchemaRule(schema: Record<string, unknown>): {
|
|
183
|
+
schema: Record<string, unknown>;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* Check if all rule results passed
|
|
187
|
+
*
|
|
188
|
+
* @param results - Array of rule results
|
|
189
|
+
* @returns Whether all rules passed
|
|
190
|
+
*/
|
|
191
|
+
export declare function allRulesPassed(results: RuleResult[]): boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Get failed rules from results
|
|
194
|
+
*
|
|
195
|
+
* @param results - Array of rule results
|
|
196
|
+
* @returns Array of failed rule results
|
|
197
|
+
*/
|
|
198
|
+
export declare function getFailedRules(results: RuleResult[]): RuleResult[];
|
|
199
|
+
/**
|
|
200
|
+
* Calculate average score from rule results
|
|
201
|
+
*
|
|
202
|
+
* @param results - Array of rule results
|
|
203
|
+
* @returns Average score (0-100)
|
|
204
|
+
*/
|
|
205
|
+
export declare function calculateAverageScore(results: RuleResult[]): number;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ThinkHive SDK v3.0 - Deterministic Graders API
|
|
4
|
+
*
|
|
5
|
+
* API for running deterministic (code-based) evaluations
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.deterministicGraders = void 0;
|
|
9
|
+
exports.createRegexRule = createRegexRule;
|
|
10
|
+
exports.createContainsRule = createContainsRule;
|
|
11
|
+
exports.createLengthRule = createLengthRule;
|
|
12
|
+
exports.createJsonSchemaRule = createJsonSchemaRule;
|
|
13
|
+
exports.allRulesPassed = allRulesPassed;
|
|
14
|
+
exports.getFailedRules = getFailedRules;
|
|
15
|
+
exports.calculateAverageScore = calculateAverageScore;
|
|
16
|
+
const client_1 = require("../core/client");
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// DETERMINISTIC GRADERS API CLIENT
|
|
19
|
+
// ============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Deterministic Graders API client for code-based evaluations
|
|
22
|
+
*/
|
|
23
|
+
exports.deterministicGraders = {
|
|
24
|
+
/**
|
|
25
|
+
* Run deterministic evaluation on a single trace
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const result = await deterministicGraders.evaluate({
|
|
30
|
+
* traceId: 'trace_123',
|
|
31
|
+
* criterionId: 'criterion_456',
|
|
32
|
+
* });
|
|
33
|
+
* console.log(`Passed: ${result.passed}, Score: ${result.score}`);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
async evaluate(options) {
|
|
37
|
+
return (0, client_1.apiRequestWithData)('/deterministic-graders/evaluate', {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
body: options,
|
|
40
|
+
apiVersion: 'v1',
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
/**
|
|
44
|
+
* Run deterministic evaluations on multiple traces
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const { results, summary } = await deterministicGraders.bulkEvaluate({
|
|
49
|
+
* evaluations: [
|
|
50
|
+
* { traceId: 'trace_1', criterionId: 'criterion_456' },
|
|
51
|
+
* { traceId: 'trace_2', criterionId: 'criterion_456' },
|
|
52
|
+
* { traceId: 'trace_3', criterionId: 'criterion_456' },
|
|
53
|
+
* ],
|
|
54
|
+
* });
|
|
55
|
+
* console.log(`Pass rate: ${summary.passRate * 100}%`);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
async bulkEvaluate(options) {
|
|
59
|
+
return (0, client_1.apiRequestWithData)('/deterministic-graders/bulk-evaluate', {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
body: options,
|
|
62
|
+
apiVersion: 'v1',
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
* Get available rule types with descriptions
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const ruleTypes = await deterministicGraders.getRuleTypes();
|
|
71
|
+
* for (const type of ruleTypes) {
|
|
72
|
+
* console.log(`${type.name}: ${type.description}`);
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
async getRuleTypes() {
|
|
77
|
+
return (0, client_1.apiRequestWithData)('/deterministic-graders/rule-types', { apiVersion: 'v1' });
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
* Get rule templates
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* const templates = await deterministicGraders.getTemplates();
|
|
85
|
+
* const noPiiTemplate = templates.find(t => t.id === 'no_pii');
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
async getTemplates() {
|
|
89
|
+
return (0, client_1.apiRequestWithData)('/deterministic-graders/templates', { apiVersion: 'v1' });
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// HELPER FUNCTIONS
|
|
94
|
+
// ============================================================================
|
|
95
|
+
/**
|
|
96
|
+
* Create a regex rule configuration
|
|
97
|
+
*
|
|
98
|
+
* @param pattern - Regular expression pattern
|
|
99
|
+
* @param flags - Regex flags (default: 'gi')
|
|
100
|
+
* @returns Rule configuration object
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const config = createRegexRule('\\b(error|fail)\\b', 'gi');
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
function createRegexRule(pattern, flags = 'gi') {
|
|
108
|
+
return { pattern, flags };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Create a contains rule configuration
|
|
112
|
+
*
|
|
113
|
+
* @param values - Strings to check for
|
|
114
|
+
* @param caseSensitive - Whether comparison is case-sensitive
|
|
115
|
+
* @returns Rule configuration object
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* const config = createContainsRule(['hello', 'hi', 'hey'], false);
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
function createContainsRule(values, caseSensitive = false) {
|
|
123
|
+
return { values, caseSensitive };
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create a length rule configuration
|
|
127
|
+
*
|
|
128
|
+
* @param min - Minimum length (optional)
|
|
129
|
+
* @param max - Maximum length (optional)
|
|
130
|
+
* @returns Rule configuration object
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* const config = createLengthRule(50, 1000);
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
function createLengthRule(min, max) {
|
|
138
|
+
return { min, max };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Create a JSON schema rule configuration
|
|
142
|
+
*
|
|
143
|
+
* @param schema - JSON Schema object
|
|
144
|
+
* @returns Rule configuration object
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* const config = createJsonSchemaRule({
|
|
149
|
+
* type: 'object',
|
|
150
|
+
* required: ['name', 'email'],
|
|
151
|
+
* properties: {
|
|
152
|
+
* name: { type: 'string' },
|
|
153
|
+
* email: { type: 'string', format: 'email' },
|
|
154
|
+
* },
|
|
155
|
+
* });
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
function createJsonSchemaRule(schema) {
|
|
159
|
+
return { schema };
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if all rule results passed
|
|
163
|
+
*
|
|
164
|
+
* @param results - Array of rule results
|
|
165
|
+
* @returns Whether all rules passed
|
|
166
|
+
*/
|
|
167
|
+
function allRulesPassed(results) {
|
|
168
|
+
return results.every(r => r.passed);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get failed rules from results
|
|
172
|
+
*
|
|
173
|
+
* @param results - Array of rule results
|
|
174
|
+
* @returns Array of failed rule results
|
|
175
|
+
*/
|
|
176
|
+
function getFailedRules(results) {
|
|
177
|
+
return results.filter(r => !r.passed);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Calculate average score from rule results
|
|
181
|
+
*
|
|
182
|
+
* @param results - Array of rule results
|
|
183
|
+
* @returns Average score (0-100)
|
|
184
|
+
*/
|
|
185
|
+
function calculateAverageScore(results) {
|
|
186
|
+
if (results.length === 0)
|
|
187
|
+
return 0;
|
|
188
|
+
const sum = results.reduce((acc, r) => acc + r.score, 0);
|
|
189
|
+
return sum / results.length;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV0ZXJtaW5pc3RpYy1ncmFkZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwaS9kZXRlcm1pbmlzdGljLWdyYWRlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7O0dBSUc7OztBQXNMSCwwQ0FFQztBQWNELGdEQUtDO0FBY0QsNENBRUM7QUFvQkQsb0RBRUM7QUFRRCx3Q0FFQztBQVFELHdDQUVDO0FBUUQsc0RBSUM7QUEvUUQsMkNBQW9EO0FBOEVwRCwrRUFBK0U7QUFDL0UsbUNBQW1DO0FBQ25DLCtFQUErRTtBQUUvRTs7R0FFRztBQUNVLFFBQUEsb0JBQW9CLEdBQUc7SUFDbEM7Ozs7Ozs7Ozs7O09BV0c7SUFDSCxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQXdCO1FBQ3JDLE9BQU8sSUFBQSwyQkFBa0IsRUFBMEIsaUNBQWlDLEVBQUU7WUFDcEYsTUFBTSxFQUFFLE1BQU07WUFDZCxJQUFJLEVBQUUsT0FBTztZQUNiLFVBQVUsRUFBRSxJQUFJO1NBQ2pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNILEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBNEI7UUFDN0MsT0FBTyxJQUFBLDJCQUFrQixFQUFxQixzQ0FBc0MsRUFBRTtZQUNwRixNQUFNLEVBQUUsTUFBTTtZQUNkLElBQUksRUFBRSxPQUFPO1lBQ2IsVUFBVSxFQUFFLElBQUk7U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSCxLQUFLLENBQUMsWUFBWTtRQUNoQixPQUFPLElBQUEsMkJBQWtCLEVBQ3ZCLG1DQUFtQyxFQUNuQyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FDckIsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNILEtBQUssQ0FBQyxZQUFZO1FBQ2hCLE9BQU8sSUFBQSwyQkFBa0IsRUFDdkIsa0NBQWtDLEVBQ2xDLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUNyQixDQUFDO0lBQ0osQ0FBQztDQUNGLENBQUM7QUFFRiwrRUFBK0U7QUFDL0UsbUJBQW1CO0FBQ25CLCtFQUErRTtBQUUvRTs7Ozs7Ozs7Ozs7R0FXRztBQUNILFNBQWdCLGVBQWUsQ0FBQyxPQUFlLEVBQUUsS0FBSyxHQUFHLElBQUk7SUFDM0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQztBQUM1QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxTQUFnQixrQkFBa0IsQ0FDaEMsTUFBZ0IsRUFDaEIsYUFBYSxHQUFHLEtBQUs7SUFFckIsT0FBTyxFQUFFLE1BQU0sRUFBRSxhQUFhLEVBQUUsQ0FBQztBQUNuQyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxHQUFZLEVBQUUsR0FBWTtJQUN6RCxPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDO0FBQ3RCLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxTQUFnQixvQkFBb0IsQ0FBQyxNQUErQjtJQUNsRSxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUM7QUFDcEIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsY0FBYyxDQUFDLE9BQXFCO0lBQ2xELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN0QyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixjQUFjLENBQUMsT0FBcUI7SUFDbEQsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDeEMsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IscUJBQXFCLENBQUMsT0FBcUI7SUFDekQsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUNuQyxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekQsT0FBTyxHQUFHLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGlua0hpdmUgU0RLIHYzLjAgLSBEZXRlcm1pbmlzdGljIEdyYWRlcnMgQVBJXG4gKlxuICogQVBJIGZvciBydW5uaW5nIGRldGVybWluaXN0aWMgKGNvZGUtYmFzZWQpIGV2YWx1YXRpb25zXG4gKi9cblxuaW1wb3J0IHsgYXBpUmVxdWVzdFdpdGhEYXRhIH0gZnJvbSAnLi4vY29yZS9jbGllbnQnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgdHlwZSBSdWxlVHlwZSA9XG4gIHwgJ3JlZ2V4J1xuICB8ICdjb250YWlucydcbiAgfCAnbm90X2NvbnRhaW5zJ1xuICB8ICdqc29uX3ZhbGlkJ1xuICB8ICdqc29uX3NjaGVtYSdcbiAgfCAnbGVuZ3RoJ1xuICB8ICdwaWlfY2hlY2snXG4gIHwgJ3NlbnRpbWVudCdcbiAgfCAnbGF0ZW5jeSdcbiAgfCAndG9rZW5fY291bnQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIERldGVybWluaXN0aWNFdmFsUmVzdWx0IHtcbiAgcGFzc2VkOiBib29sZWFuO1xuICBzY29yZTogbnVtYmVyO1xuICByZWFzb25pbmc6IHN0cmluZztcbiAgcnVsZVJlc3VsdHM/OiBSdWxlUmVzdWx0W107XG4gIG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUnVsZVJlc3VsdCB7XG4gIHJ1bGVJZDogc3RyaW5nO1xuICBydWxlTmFtZTogc3RyaW5nO1xuICBydWxlVHlwZTogUnVsZVR5cGU7XG4gIHBhc3NlZDogYm9vbGVhbjtcbiAgc2NvcmU6IG51bWJlcjtcbiAgZGV0YWlscz86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFdmFsdWF0ZU9wdGlvbnMge1xuICB0cmFjZUlkOiBzdHJpbmc7XG4gIGNyaXRlcmlvbklkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQnVsa0V2YWx1YXRlT3B0aW9ucyB7XG4gIGV2YWx1YXRpb25zOiBBcnJheTx7XG4gICAgdHJhY2VJZDogc3RyaW5nO1xuICAgIGNyaXRlcmlvbklkOiBzdHJpbmc7XG4gIH0+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1bGtFdmFsdWF0ZVJlc3VsdCB7XG4gIHJlc3VsdHM6IEFycmF5PHtcbiAgICB0cmFjZUlkOiBzdHJpbmc7XG4gICAgY3JpdGVyaW9uSWQ6IHN0cmluZztcbiAgICBwYXNzZWQ6IGJvb2xlYW47XG4gICAgc2NvcmU6IG51bWJlcjtcbiAgICBlcnJvcj86IHN0cmluZztcbiAgfT47XG4gIHN1bW1hcnk6IHtcbiAgICB0b3RhbDogbnVtYmVyO1xuICAgIHBhc3NlZDogbnVtYmVyO1xuICAgIGZhaWxlZDogbnVtYmVyO1xuICAgIHBhc3NSYXRlOiBudW1iZXI7XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUnVsZVR5cGVJbmZvIHtcbiAgaWQ6IFJ1bGVUeXBlO1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGNvbmZpZ0ZpZWxkczogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUnVsZVRlbXBsYXRlIHtcbiAgaWQ6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICBydWxlVHlwZTogUnVsZVR5cGU7XG4gIGNvbmZpZzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERFVEVSTUlOSVNUSUMgR1JBREVSUyBBUEkgQ0xJRU5UXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogRGV0ZXJtaW5pc3RpYyBHcmFkZXJzIEFQSSBjbGllbnQgZm9yIGNvZGUtYmFzZWQgZXZhbHVhdGlvbnNcbiAqL1xuZXhwb3J0IGNvbnN0IGRldGVybWluaXN0aWNHcmFkZXJzID0ge1xuICAvKipcbiAgICogUnVuIGRldGVybWluaXN0aWMgZXZhbHVhdGlvbiBvbiBhIHNpbmdsZSB0cmFjZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRldGVybWluaXN0aWNHcmFkZXJzLmV2YWx1YXRlKHtcbiAgICogICB0cmFjZUlkOiAndHJhY2VfMTIzJyxcbiAgICogICBjcml0ZXJpb25JZDogJ2NyaXRlcmlvbl80NTYnLFxuICAgKiB9KTtcbiAgICogY29uc29sZS5sb2coYFBhc3NlZDogJHtyZXN1bHQucGFzc2VkfSwgU2NvcmU6ICR7cmVzdWx0LnNjb3JlfWApO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGV2YWx1YXRlKG9wdGlvbnM6IEV2YWx1YXRlT3B0aW9ucyk6IFByb21pc2U8RGV0ZXJtaW5pc3RpY0V2YWxSZXN1bHQ+IHtcbiAgICByZXR1cm4gYXBpUmVxdWVzdFdpdGhEYXRhPERldGVybWluaXN0aWNFdmFsUmVzdWx0PignL2RldGVybWluaXN0aWMtZ3JhZGVycy9ldmFsdWF0ZScsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIGFwaVZlcnNpb246ICd2MScsXG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJ1biBkZXRlcm1pbmlzdGljIGV2YWx1YXRpb25zIG9uIG11bHRpcGxlIHRyYWNlc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHsgcmVzdWx0cywgc3VtbWFyeSB9ID0gYXdhaXQgZGV0ZXJtaW5pc3RpY0dyYWRlcnMuYnVsa0V2YWx1YXRlKHtcbiAgICogICBldmFsdWF0aW9uczogW1xuICAgKiAgICAgeyB0cmFjZUlkOiAndHJhY2VfMScsIGNyaXRlcmlvbklkOiAnY3JpdGVyaW9uXzQ1NicgfSxcbiAgICogICAgIHsgdHJhY2VJZDogJ3RyYWNlXzInLCBjcml0ZXJpb25JZDogJ2NyaXRlcmlvbl80NTYnIH0sXG4gICAqICAgICB7IHRyYWNlSWQ6ICd0cmFjZV8zJywgY3JpdGVyaW9uSWQ6ICdjcml0ZXJpb25fNDU2JyB9LFxuICAgKiAgIF0sXG4gICAqIH0pO1xuICAgKiBjb25zb2xlLmxvZyhgUGFzcyByYXRlOiAke3N1bW1hcnkucGFzc1JhdGUgKiAxMDB9JWApO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGJ1bGtFdmFsdWF0ZShvcHRpb25zOiBCdWxrRXZhbHVhdGVPcHRpb25zKTogUHJvbWlzZTxCdWxrRXZhbHVhdGVSZXN1bHQ+IHtcbiAgICByZXR1cm4gYXBpUmVxdWVzdFdpdGhEYXRhPEJ1bGtFdmFsdWF0ZVJlc3VsdD4oJy9kZXRlcm1pbmlzdGljLWdyYWRlcnMvYnVsay1ldmFsdWF0ZScsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIGFwaVZlcnNpb246ICd2MScsXG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBhdmFpbGFibGUgcnVsZSB0eXBlcyB3aXRoIGRlc2NyaXB0aW9uc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHJ1bGVUeXBlcyA9IGF3YWl0IGRldGVybWluaXN0aWNHcmFkZXJzLmdldFJ1bGVUeXBlcygpO1xuICAgKiBmb3IgKGNvbnN0IHR5cGUgb2YgcnVsZVR5cGVzKSB7XG4gICAqICAgY29uc29sZS5sb2coYCR7dHlwZS5uYW1lfTogJHt0eXBlLmRlc2NyaXB0aW9ufWApO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgZ2V0UnVsZVR5cGVzKCk6IFByb21pc2U8UnVsZVR5cGVJbmZvW10+IHtcbiAgICByZXR1cm4gYXBpUmVxdWVzdFdpdGhEYXRhPFJ1bGVUeXBlSW5mb1tdPihcbiAgICAgICcvZGV0ZXJtaW5pc3RpYy1ncmFkZXJzL3J1bGUtdHlwZXMnLFxuICAgICAgeyBhcGlWZXJzaW9uOiAndjEnIH1cbiAgICApO1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZXQgcnVsZSB0ZW1wbGF0ZXNcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCB0ZW1wbGF0ZXMgPSBhd2FpdCBkZXRlcm1pbmlzdGljR3JhZGVycy5nZXRUZW1wbGF0ZXMoKTtcbiAgICogY29uc3Qgbm9QaWlUZW1wbGF0ZSA9IHRlbXBsYXRlcy5maW5kKHQgPT4gdC5pZCA9PT0gJ25vX3BpaScpO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGdldFRlbXBsYXRlcygpOiBQcm9taXNlPFJ1bGVUZW1wbGF0ZVtdPiB7XG4gICAgcmV0dXJuIGFwaVJlcXVlc3RXaXRoRGF0YTxSdWxlVGVtcGxhdGVbXT4oXG4gICAgICAnL2RldGVybWluaXN0aWMtZ3JhZGVycy90ZW1wbGF0ZXMnLFxuICAgICAgeyBhcGlWZXJzaW9uOiAndjEnIH1cbiAgICApO1xuICB9LFxufTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENyZWF0ZSBhIHJlZ2V4IHJ1bGUgY29uZmlndXJhdGlvblxuICpcbiAqIEBwYXJhbSBwYXR0ZXJuIC0gUmVndWxhciBleHByZXNzaW9uIHBhdHRlcm5cbiAqIEBwYXJhbSBmbGFncyAtIFJlZ2V4IGZsYWdzIChkZWZhdWx0OiAnZ2knKVxuICogQHJldHVybnMgUnVsZSBjb25maWd1cmF0aW9uIG9iamVjdFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjb25maWcgPSBjcmVhdGVSZWdleFJ1bGUoJ1xcXFxiKGVycm9yfGZhaWwpXFxcXGInLCAnZ2knKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVnZXhSdWxlKHBhdHRlcm46IHN0cmluZywgZmxhZ3MgPSAnZ2knKTogeyBwYXR0ZXJuOiBzdHJpbmc7IGZsYWdzOiBzdHJpbmcgfSB7XG4gIHJldHVybiB7IHBhdHRlcm4sIGZsYWdzIH07XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgY29udGFpbnMgcnVsZSBjb25maWd1cmF0aW9uXG4gKlxuICogQHBhcmFtIHZhbHVlcyAtIFN0cmluZ3MgdG8gY2hlY2sgZm9yXG4gKiBAcGFyYW0gY2FzZVNlbnNpdGl2ZSAtIFdoZXRoZXIgY29tcGFyaXNvbiBpcyBjYXNlLXNlbnNpdGl2ZVxuICogQHJldHVybnMgUnVsZSBjb25maWd1cmF0aW9uIG9iamVjdFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjb25maWcgPSBjcmVhdGVDb250YWluc1J1bGUoWydoZWxsbycsICdoaScsICdoZXknXSwgZmFsc2UpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb250YWluc1J1bGUoXG4gIHZhbHVlczogc3RyaW5nW10sXG4gIGNhc2VTZW5zaXRpdmUgPSBmYWxzZVxuKTogeyB2YWx1ZXM6IHN0cmluZ1tdOyBjYXNlU2Vuc2l0aXZlOiBib29sZWFuIH0ge1xuICByZXR1cm4geyB2YWx1ZXMsIGNhc2VTZW5zaXRpdmUgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBsZW5ndGggcnVsZSBjb25maWd1cmF0aW9uXG4gKlxuICogQHBhcmFtIG1pbiAtIE1pbmltdW0gbGVuZ3RoIChvcHRpb25hbClcbiAqIEBwYXJhbSBtYXggLSBNYXhpbXVtIGxlbmd0aCAob3B0aW9uYWwpXG4gKiBAcmV0dXJucyBSdWxlIGNvbmZpZ3VyYXRpb24gb2JqZWN0XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGNvbmZpZyA9IGNyZWF0ZUxlbmd0aFJ1bGUoNTAsIDEwMDApO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVMZW5ndGhSdWxlKG1pbj86IG51bWJlciwgbWF4PzogbnVtYmVyKTogeyBtaW4/OiBudW1iZXI7IG1heD86IG51bWJlciB9IHtcbiAgcmV0dXJuIHsgbWluLCBtYXggfTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBKU09OIHNjaGVtYSBydWxlIGNvbmZpZ3VyYXRpb25cbiAqXG4gKiBAcGFyYW0gc2NoZW1hIC0gSlNPTiBTY2hlbWEgb2JqZWN0XG4gKiBAcmV0dXJucyBSdWxlIGNvbmZpZ3VyYXRpb24gb2JqZWN0XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGNvbmZpZyA9IGNyZWF0ZUpzb25TY2hlbWFSdWxlKHtcbiAqICAgdHlwZTogJ29iamVjdCcsXG4gKiAgIHJlcXVpcmVkOiBbJ25hbWUnLCAnZW1haWwnXSxcbiAqICAgcHJvcGVydGllczoge1xuICogICAgIG5hbWU6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAqICAgICBlbWFpbDogeyB0eXBlOiAnc3RyaW5nJywgZm9ybWF0OiAnZW1haWwnIH0sXG4gKiAgIH0sXG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSnNvblNjaGVtYVJ1bGUoc2NoZW1hOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHsgc2NoZW1hOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgcmV0dXJuIHsgc2NoZW1hIH07XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgYWxsIHJ1bGUgcmVzdWx0cyBwYXNzZWRcbiAqXG4gKiBAcGFyYW0gcmVzdWx0cyAtIEFycmF5IG9mIHJ1bGUgcmVzdWx0c1xuICogQHJldHVybnMgV2hldGhlciBhbGwgcnVsZXMgcGFzc2VkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhbGxSdWxlc1Bhc3NlZChyZXN1bHRzOiBSdWxlUmVzdWx0W10pOiBib29sZWFuIHtcbiAgcmV0dXJuIHJlc3VsdHMuZXZlcnkociA9PiByLnBhc3NlZCk7XG59XG5cbi8qKlxuICogR2V0IGZhaWxlZCBydWxlcyBmcm9tIHJlc3VsdHNcbiAqXG4gKiBAcGFyYW0gcmVzdWx0cyAtIEFycmF5IG9mIHJ1bGUgcmVzdWx0c1xuICogQHJldHVybnMgQXJyYXkgb2YgZmFpbGVkIHJ1bGUgcmVzdWx0c1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmFpbGVkUnVsZXMocmVzdWx0czogUnVsZVJlc3VsdFtdKTogUnVsZVJlc3VsdFtdIHtcbiAgcmV0dXJuIHJlc3VsdHMuZmlsdGVyKHIgPT4gIXIucGFzc2VkKTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgYXZlcmFnZSBzY29yZSBmcm9tIHJ1bGUgcmVzdWx0c1xuICpcbiAqIEBwYXJhbSByZXN1bHRzIC0gQXJyYXkgb2YgcnVsZSByZXN1bHRzXG4gKiBAcmV0dXJucyBBdmVyYWdlIHNjb3JlICgwLTEwMClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUF2ZXJhZ2VTY29yZShyZXN1bHRzOiBSdWxlUmVzdWx0W10pOiBudW1iZXIge1xuICBpZiAocmVzdWx0cy5sZW5ndGggPT09IDApIHJldHVybiAwO1xuICBjb25zdCBzdW0gPSByZXN1bHRzLnJlZHVjZSgoYWNjLCByKSA9PiBhY2MgKyByLnNjb3JlLCAwKTtcbiAgcmV0dXJuIHN1bSAvIHJlc3VsdHMubGVuZ3RoO1xufVxuIl19
|