@thinkhive/sdk 3.1.1 → 4.0.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.
@@ -0,0 +1,200 @@
1
+ /**
2
+ * ThinkHive SDK v3.0 - Conversation Evaluation API
3
+ *
4
+ * API for multi-turn conversation evaluation
5
+ */
6
+ export type AggregateMethod = 'worst' | 'average' | 'weighted' | 'final_turn' | 'majority';
7
+ export interface SessionTrace {
8
+ id: string;
9
+ sessionId: string;
10
+ turnNumber: number;
11
+ userMessage: string;
12
+ agentResponse: string;
13
+ timestamp: string;
14
+ metadata?: Record<string, unknown>;
15
+ }
16
+ export interface TurnEvaluation {
17
+ traceId: string;
18
+ turnNumber: number;
19
+ passed: boolean;
20
+ score: number;
21
+ reasoning: string;
22
+ }
23
+ export interface ConversationEvalResult {
24
+ sessionId: string;
25
+ criterionId: string;
26
+ turnCount: number;
27
+ turnResults: TurnEvaluation[];
28
+ aggregatePassed: boolean;
29
+ aggregateScore: number;
30
+ aggregateMethod: AggregateMethod;
31
+ reasoning: string;
32
+ metadata?: Record<string, unknown>;
33
+ }
34
+ export interface EvaluateConversationOptions {
35
+ sessionId: string;
36
+ criterionId: string;
37
+ options?: {
38
+ aggregateMethod?: AggregateMethod;
39
+ minTurns?: number;
40
+ maxTurns?: number;
41
+ };
42
+ }
43
+ export interface AggregationMethodInfo {
44
+ id: AggregateMethod;
45
+ name: string;
46
+ description: string;
47
+ useCase: string;
48
+ }
49
+ /**
50
+ * Conversation Evaluation API client for multi-turn evaluation
51
+ */
52
+ export declare const conversationEval: {
53
+ /**
54
+ * Get traces for a conversation session
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const traces = await conversationEval.getSessionTraces('session_123');
59
+ * console.log(`Conversation has ${traces.length} turns`);
60
+ * ```
61
+ */
62
+ getSessionTraces(sessionId: string): Promise<SessionTrace[]>;
63
+ /**
64
+ * Run conversation-level evaluation
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const result = await conversationEval.evaluate({
69
+ * sessionId: 'session_123',
70
+ * criterionId: 'criterion_456',
71
+ * options: {
72
+ * aggregateMethod: 'average',
73
+ * minTurns: 2,
74
+ * },
75
+ * });
76
+ * console.log(`Conversation score: ${result.aggregateScore}`);
77
+ * ```
78
+ */
79
+ evaluate(options: EvaluateConversationOptions): Promise<ConversationEvalResult>;
80
+ /**
81
+ * Get available aggregation methods with descriptions
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const methods = await conversationEval.getAggregationMethods();
86
+ * for (const method of methods) {
87
+ * console.log(`${method.name}: ${method.description}`);
88
+ * }
89
+ * ```
90
+ */
91
+ getAggregationMethods(): Promise<AggregationMethodInfo[]>;
92
+ };
93
+ /**
94
+ * Calculate worst-turn aggregation
95
+ *
96
+ * @param turnResults - Array of turn evaluation results
97
+ * @returns Aggregated result using worst turn logic
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const result = aggregateWorst(turnResults);
102
+ * // Fails if any turn fails
103
+ * ```
104
+ */
105
+ export declare function aggregateWorst(turnResults: TurnEvaluation[]): {
106
+ passed: boolean;
107
+ score: number;
108
+ };
109
+ /**
110
+ * Calculate average aggregation
111
+ *
112
+ * @param turnResults - Array of turn evaluation results
113
+ * @returns Aggregated result using average logic
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const result = aggregateAverage(turnResults);
118
+ * ```
119
+ */
120
+ export declare function aggregateAverage(turnResults: TurnEvaluation[]): {
121
+ passed: boolean;
122
+ score: number;
123
+ };
124
+ /**
125
+ * Calculate weighted average aggregation (later turns weighted more)
126
+ *
127
+ * @param turnResults - Array of turn evaluation results
128
+ * @returns Aggregated result using weighted average logic
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const result = aggregateWeighted(turnResults);
133
+ * // Later turns have higher weight
134
+ * ```
135
+ */
136
+ export declare function aggregateWeighted(turnResults: TurnEvaluation[]): {
137
+ passed: boolean;
138
+ score: number;
139
+ };
140
+ /**
141
+ * Calculate final-turn aggregation
142
+ *
143
+ * @param turnResults - Array of turn evaluation results
144
+ * @returns Aggregated result using only the final turn
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const result = aggregateFinalTurn(turnResults);
149
+ * // Only final turn matters
150
+ * ```
151
+ */
152
+ export declare function aggregateFinalTurn(turnResults: TurnEvaluation[]): {
153
+ passed: boolean;
154
+ score: number;
155
+ };
156
+ /**
157
+ * Calculate majority vote aggregation
158
+ *
159
+ * @param turnResults - Array of turn evaluation results
160
+ * @returns Aggregated result using majority vote logic
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * const result = aggregateMajority(turnResults);
165
+ * // Passes if majority of turns pass
166
+ * ```
167
+ */
168
+ export declare function aggregateMajority(turnResults: TurnEvaluation[]): {
169
+ passed: boolean;
170
+ score: number;
171
+ };
172
+ /**
173
+ * Get appropriate aggregation function for a method
174
+ *
175
+ * @param method - Aggregation method name
176
+ * @returns Aggregation function
177
+ */
178
+ export declare function getAggregator(method: AggregateMethod): (turnResults: TurnEvaluation[]) => {
179
+ passed: boolean;
180
+ score: number;
181
+ };
182
+ /**
183
+ * Find problematic turns in a conversation
184
+ *
185
+ * @param result - Conversation evaluation result
186
+ * @param scoreThreshold - Minimum acceptable score (default 70)
187
+ * @returns Array of problematic turn results
188
+ */
189
+ export declare function getProblematicTurns(result: ConversationEvalResult, scoreThreshold?: number): TurnEvaluation[];
190
+ /**
191
+ * Calculate conversation quality trend
192
+ *
193
+ * @param result - Conversation evaluation result
194
+ * @returns Trend analysis
195
+ */
196
+ export declare function analyzeConversationTrend(result: ConversationEvalResult): {
197
+ direction: 'improving' | 'declining' | 'stable';
198
+ firstHalfAvg: number;
199
+ secondHalfAvg: number;
200
+ };
@@ -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: 'none' });
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: 'none',
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: 'none' });
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udmVyc2F0aW9uLWV2YWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL2NvbnZlcnNhdGlvbi1ldmFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7OztHQUlHOzs7QUE0SUgsd0NBT0M7QUFhRCw0Q0FRQztBQWNELDhDQW1CQztBQWNELGdEQUtDO0FBY0QsOENBUUM7QUFRRCxzQ0FXQztBQVNELGtEQUtDO0FBUUQsNERBeUJDO0FBbFRELDJDQUFvRDtBQXVEcEQsK0VBQStFO0FBQy9FLCtCQUErQjtBQUMvQiwrRUFBK0U7QUFFL0U7O0dBRUc7QUFDVSxRQUFBLGdCQUFnQixHQUFHO0lBQzlCOzs7Ozs7OztPQVFHO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUFDLFNBQWlCO1FBQ3RDLE9BQU8sSUFBQSwyQkFBa0IsRUFDdkIsdUNBQXVDLFNBQVMsRUFBRSxFQUNsRCxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FDdkIsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7O09BZUc7SUFDSCxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQW9DO1FBQ2pELE9BQU8sSUFBQSwyQkFBa0IsRUFBeUIsNkJBQTZCLEVBQUU7WUFDL0UsTUFBTSxFQUFFLE1BQU07WUFDZCxJQUFJLEVBQUUsT0FBTztZQUNiLFVBQVUsRUFBRSxNQUFNO1NBQ25CLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHO0lBQ0gsS0FBSyxDQUFDLHFCQUFxQjtRQUN6QixPQUFPLElBQUEsMkJBQWtCLEVBQ3ZCLHdDQUF3QyxFQUN4QyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FDdkIsQ0FBQztJQUNKLENBQUM7Q0FDRixDQUFDO0FBRUYsK0VBQStFO0FBQy9FLG1CQUFtQjtBQUNuQiwrRUFBK0U7QUFFL0U7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxTQUFnQixjQUFjLENBQUMsV0FBNkI7SUFDMUQsSUFBSSxXQUFXLENB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QU0sSUFBSSxHQUFHLGFBQWEsR0FBRyxZQUFZLENBQUM7SUFDMUMsSUFBSSxTQUErQyxDQUFDO0lBRXBELElBQUksSUFBSSxHQUFHLENBQUM7UUFBRSxTQUFTLEdBQUcsV0FBVyxDQUFDO1NBQ2pDLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQztRQUFFLFNBQVMsR0FBRyxXQUFXLENBQUM7O1FBQ3ZDLFNBQVMsR0FBRyxRQUFRLENBQUM7SUFFMUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLENBQUM7QUFDcEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhpbmtIaXZlIFNESyB2My4wIC0gQ29udmVyc2F0aW9uIEV2YWx1YXRpb24gQVBJXG4gKlxuICogQVBJIGZvciBtdWx0aS10dXJuIGNvbnZlcnNhdGlvbiBldmFsdWF0aW9uXG4gKi9cblxuaW1wb3J0IHsgYXBpUmVxdWVzdFdpdGhEYXRhIH0gZnJvbSAnLi4vY29yZS9jbGllbnQnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgdHlwZSBBZ2dyZWdhdGVNZXRob2QgPSAnd29yc3QnIHwgJ2F2ZXJhZ2UnIHwgJ3dlaWdodGVkJyB8ICdmaW5hbF90dXJuJyB8ICdtYWpvcml0eSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2Vzc2lvblRyYWNlIHtcbiAgaWQ6IHN0cmluZztcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIHR1cm5OdW1iZXI6IG51bWJlcjtcbiAgdXNlck1lc3NhZ2U6IHN0cmluZztcbiAgYWdlbnRSZXNwb25zZTogc3RyaW5nO1xuICB0aW1lc3RhbXA6IHN0cmluZztcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUdXJuRXZhbHVhdGlvbiB7XG4gIHRyYWNlSWQ6IHN0cmluZztcbiAgdHVybk51bWJlcjogbnVtYmVyO1xuICBwYXNzZWQ6IGJvb2xlYW47XG4gIHNjb3JlOiBudW1iZXI7XG4gIHJlYXNvbmluZzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnZlcnNhdGlvbkV2YWxSZXN1bHQge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgY3JpdGVyaW9uSWQ6IHN0cmluZztcbiAgdHVybkNvdW50OiBudW1iZXI7XG4gIHR1cm5SZXN1bHRzOiBUdXJuRXZhbHVhdGlvbltdO1xuICBhZ2dyZWdhdGVQYXNzZWQ6IGJvb2xlYW47XG4gIGFnZ3JlZ2F0ZVNjb3JlOiBudW1iZXI7XG4gIGFnZ3JlZ2F0ZU1ldGhvZDogQWdncmVnYXRlTWV0aG9kO1xuICByZWFzb25pbmc6IHN0cmluZztcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFdmFsdWF0ZUNvbnZlcnNhdGlvbk9wdGlvbnMge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgY3JpdGVyaW9uSWQ6IHN0cmluZztcbiAgb3B0aW9ucz86IHtcbiAgICBhZ2dyZWdhdGVNZXRob2Q/OiBBZ2dyZWdhdGVNZXRob2Q7XG4gICAgbWluVHVybnM/OiBudW1iZXI7XG4gICAgbWF4VHVybnM/OiBudW1iZXI7XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWdncmVnYXRpb25NZXRob2RJbmZvIHtcbiAgaWQ6IEFnZ3JlZ2F0ZU1ldGhvZDtcbiAgbmFtZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICB1c2VDYXNlOiBzdHJpbmc7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIENPTlZFUlNBVElPTiBFVkFMIEFQSSBDTElFTlRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDb252ZXJzYXRpb24gRXZhbHVhdGlvbiBBUEkgY2xpZW50IGZvciBtdWx0aS10dXJuIGV2YWx1YXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IGNvbnZlcnNhdGlvbkV2YWwgPSB7XG4gIC8qKlxuICAgKiBHZXQgdHJhY2VzIGZvciBhIGNvbnZlcnNhdGlvbiBzZXNzaW9uXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdHJhY2VzID0gYXdhaXQgY29udmVyc2F0aW9uRXZhbC5nZXRTZXNzaW9uVHJhY2VzKCdzZXNzaW9uXzEyMycpO1xuICAgKiBjb25zb2xlLmxvZyhgQ29udmVyc2F0aW9uIGhhcyAke3RyYWNlcy5sZW5ndGh9IHR1cm5zYCk7XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgZ2V0U2Vzc2lvblRyYWNlcyhzZXNzaW9uSWQ6IHN0cmluZyk6IFByb21pc2U8U2Vzc2lvblRyYWNlW10+IHtcbiAgICByZXR1cm4gYXBpUmVxdWVzdFdpdGhEYXRhPFNlc3Npb25UcmFjZVtdPihcbiAgICAgIGAvY29udmVyc2F0aW9uLWV2YWwvdHJhY2VzP3Nlc3Npb25JZD0ke3Nlc3Npb25JZH1gLFxuICAgICAgeyBhcGlWZXJzaW9uOiAnbm9uZScgfVxuICAgICk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJ1biBjb252ZXJzYXRpb24tbGV2ZWwgZXZhbHVhdGlvblxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnNhdGlvbkV2YWwuZXZhbHVhdGUoe1xuICAgKiAgIHNlc3Npb25JZDogJ3Nlc3Npb25fMTIzJyxcbiAgICogICBjcml0ZXJpb25JZDogJ2NyaXRlcmlvbl80NTYnLFxuICAgKiAgIG9wdGlvbnM6IHtcbiAgICogICAgIGFnZ3JlZ2F0ZU1ldGhvZDogJ2F2ZXJhZ2UnLFxuICAgKiAgICAgbWluVHVybnM6IDIsXG4gICAqICAgfSxcbiAgICogfSk7XG4gICAqIGNvbnNvbGUubG9nKGBDb252ZXJzYXRpb24gc2NvcmU6ICR7cmVzdWx0LmFnZ3JlZ2F0ZVNjb3JlfWApO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGV2YWx1YXRlKG9wdGlvbnM6IEV2YWx1YXRlQ29udmVyc2F0aW9uT3B0aW9ucyk6IFByb21pc2U8Q29udmVyc2F0aW9uRXZhbFJlc3VsdD4ge1xuICAgIHJldHVybiBhcGlSZXF1ZXN0V2l0aERhdGE8Q29udmVyc2F0aW9uRXZhbFJlc3VsdD4oJy9jb252ZXJzYXRpb24tZXZhbC9ldmFsdWF0ZScsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIGFwaVZlcnNpb246ICdub25lJyxcbiAgICB9KTtcbiAgfSxcblxuICAvKipcbiAgICogR2V0IGF2YWlsYWJsZSBhZ2dyZWdhdGlvbiBtZXRob2RzIHdpdGggZGVzY3JpcHRpb25zXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgbWV0aG9kcyA9IGF3YWl0IGNvbnZlcnNhdGlvbkV2YWwuZ2V0QWdncmVnYXRpb25NZXRob2RzKCk7XG4gICAqIGZvciAoY29uc3QgbWV0aG9kIG9mIG1ldGhvZHMpIHtcbiAgICogICBjb25zb2xlLmxvZyhgJHttZXRob2QubmFtZX06ICR7bWV0aG9kLmRlc2NyaXB0aW9ufWApO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgZ2V0QWdncmVnYXRpb25NZXRob2RzKCk6IFByb21pc2U8QWdncmVnYXRpb25NZXRob2RJbmZvW10+IHtcbiAgICByZXR1cm4gYXBpUmVxdWVzdFdpdGhEYXRhPEFnZ3JlZ2F0aW9uTWV0aG9kSW5mb1tdPihcbiAgICAgICcvY29udmVyc2F0aW9uLWV2YWwvYWdncmVnYXRpb24tbWV0aG9kcycsXG4gICAgICB7IGFwaVZlcnNpb246ICdub25lJyB9XG4gICAgKTtcbiAgfSxcbn07XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDYWxjdWxhdGUgd29yc3QtdHVybiBhZ2dyZWdhdGlvblxuICpcbiAqIEBwYXJhbSB0dXJuUmVzdWx0cyAtIEFycmF5IG9mIHR1cm4gZXZhbHVhdGlvbiByZXN1bHRzXG4gKiBAcmV0dXJucyBBZ2dyZWdhdGVkIHJlc3VsdCB1c2luZyB3b3JzdCB0dXJuIGxvZ2ljXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHJlc3VsdCA9IGFnZ3JlZ2F0ZVdvcnN0KHR1cm5SZXN1bHRzKTtcbiAqIC8vIEZhaWxzIGlmIGFueSB0dXJuIGZhaWxzXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFnZ3JlZ2F0ZVdvcnN0KHR1cm5SZXN1bHRzOiBUdXJuRXZhbHVhdGlvbltdKTogeyBwYXNzZWQ6IGJvb2xlYW47IHNjb3JlOiBudW1iZXIgfSB7XG4gIGlmICh0dXJuUmVzdWx0cy5sZW5ndGggPT09IDApIHJldHVybiB7IHBhc3NlZDogZmFsc2UsIHNjb3JlOiAwIH07XG5cbiAgY29uc3Qgd29yc3RTY29yZSA9IE1hdGgubWluKC4uLnR1cm5SZXN1bHRzLm1hcCh0ID0+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;