@goreal-ai/echo-pdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-judge/index.d.ts +177 -0
- package/dist/ai-judge/index.d.ts.map +1 -0
- package/dist/ai-judge/index.js +299 -0
- package/dist/ai-judge/index.js.map +1 -0
- package/dist/evaluator/evaluator.d.ts +136 -0
- package/dist/evaluator/evaluator.d.ts.map +1 -0
- package/dist/evaluator/evaluator.js +407 -0
- package/dist/evaluator/evaluator.js.map +1 -0
- package/dist/evaluator/index.d.ts +7 -0
- package/dist/evaluator/index.d.ts.map +1 -0
- package/dist/evaluator/index.js +8 -0
- package/dist/evaluator/index.js.map +1 -0
- package/dist/evaluator/operators.d.ts +105 -0
- package/dist/evaluator/operators.d.ts.map +1 -0
- package/dist/evaluator/operators.js +371 -0
- package/dist/evaluator/operators.js.map +1 -0
- package/dist/index.d.ts +115 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +388 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/ast.d.ts +106 -0
- package/dist/parser/ast.d.ts.map +1 -0
- package/dist/parser/ast.js +260 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/index.d.ts +8 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +13 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/lexer.d.ts +199 -0
- package/dist/parser/lexer.d.ts.map +1 -0
- package/dist/parser/lexer.js +491 -0
- package/dist/parser/lexer.js.map +1 -0
- package/dist/parser/parser.d.ts +49 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +615 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/plugins/index.d.ts +62 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +170 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/renderer/index.d.ts +6 -0
- package/dist/renderer/index.d.ts.map +1 -0
- package/dist/renderer/index.js +5 -0
- package/dist/renderer/index.js.map +1 -0
- package/dist/renderer/renderer.d.ts +97 -0
- package/dist/renderer/renderer.d.ts.map +1 -0
- package/dist/renderer/renderer.js +243 -0
- package/dist/renderer/renderer.js.map +1 -0
- package/dist/types.d.ts +255 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview AI Judge - LLM-based condition evaluation
|
|
3
|
+
*
|
|
4
|
+
* This module handles the #ai_judge operator which queries an LLM
|
|
5
|
+
* to evaluate boolean conditions.
|
|
6
|
+
*
|
|
7
|
+
* FEATURES:
|
|
8
|
+
* - Provider abstraction for different backends (OpenAI, Anthropic)
|
|
9
|
+
* - Automatic caching with TTL to avoid redundant API calls
|
|
10
|
+
* - Structured prompts for consistent yes/no answers
|
|
11
|
+
* - Graceful error handling
|
|
12
|
+
*
|
|
13
|
+
* API KEY CONFIGURATION:
|
|
14
|
+
* The API key can be provided in three ways (in priority order):
|
|
15
|
+
* 1. Programmatic: createEcho({ aiProvider: { apiKey: '...' } })
|
|
16
|
+
* 2. Environment: ECHO_API_KEY or OPENAI_API_KEY
|
|
17
|
+
* 3. Config file: echo.config.yaml (aiProvider.apiKey)
|
|
18
|
+
*/
|
|
19
|
+
import type { AIProviderConfig } from '../types.js';
|
|
20
|
+
/**
|
|
21
|
+
* AI Provider interface for evaluating boolean conditions.
|
|
22
|
+
*/
|
|
23
|
+
export interface AIProvider {
|
|
24
|
+
/**
|
|
25
|
+
* Evaluate a boolean question about a value.
|
|
26
|
+
*
|
|
27
|
+
* @param value - The value to evaluate
|
|
28
|
+
* @param question - The yes/no question to ask
|
|
29
|
+
* @returns true or false based on the AI's response
|
|
30
|
+
*/
|
|
31
|
+
evaluate(value: unknown, question: string): Promise<boolean>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create an OpenAI-based AI provider.
|
|
35
|
+
*
|
|
36
|
+
* @param config - Configuration with API key and model
|
|
37
|
+
* @returns AIProvider using OpenAI
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const provider = createOpenAIProvider({
|
|
42
|
+
* type: 'openai',
|
|
43
|
+
* apiKey: process.env.OPENAI_API_KEY,
|
|
44
|
+
* model: 'gpt-4o-mini',
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* const result = await provider.evaluate(
|
|
48
|
+
* 'This is a family-friendly movie.',
|
|
49
|
+
* 'Is this content appropriate for children?'
|
|
50
|
+
* );
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function createOpenAIProvider(config: AIProviderConfig): AIProvider;
|
|
54
|
+
/**
|
|
55
|
+
* Build the prompt for the AI judge.
|
|
56
|
+
*
|
|
57
|
+
* The prompt is designed to get a clear yes/no answer.
|
|
58
|
+
*
|
|
59
|
+
* @param value - The value to evaluate
|
|
60
|
+
* @param question - The question to ask
|
|
61
|
+
* @returns Formatted prompt string
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildPrompt(value: unknown, question: string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Create an AI Judge instance with the given configuration.
|
|
66
|
+
*
|
|
67
|
+
* @param config - AI provider configuration
|
|
68
|
+
* @returns An AIProvider implementation
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* const judge = createAIJudge({
|
|
73
|
+
* type: 'openai',
|
|
74
|
+
* apiKey: process.env.OPENAI_API_KEY,
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* const isAppropriate = await judge.evaluate(content, 'Is this safe for work?');
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function createAIJudge(config: AIProviderConfig): AIProvider;
|
|
81
|
+
/**
|
|
82
|
+
* Options for creating a cache key.
|
|
83
|
+
*/
|
|
84
|
+
export interface CacheKeyOptions {
|
|
85
|
+
/** The value being evaluated (can be very large, e.g., 200K tokens) */
|
|
86
|
+
value: unknown;
|
|
87
|
+
/** The boolean question to ask */
|
|
88
|
+
question: string;
|
|
89
|
+
/** The AI provider type (e.g., 'openai', 'anthropic') */
|
|
90
|
+
provider?: string;
|
|
91
|
+
/** The model identifier (e.g., 'gpt-4o-mini') */
|
|
92
|
+
model?: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create a cache key for an AI judge evaluation.
|
|
96
|
+
*
|
|
97
|
+
* Uses SHA-256 hashing to create a fixed-size key regardless of input size.
|
|
98
|
+
* This is critical because the value being evaluated can be extremely large
|
|
99
|
+
* (e.g., a 200K token document). Storing the raw value as a Map key would
|
|
100
|
+
* cause severe memory bloat.
|
|
101
|
+
*
|
|
102
|
+
* The hash includes provider and model to prevent cache collisions when
|
|
103
|
+
* multiple Echo instances use different AI configurations.
|
|
104
|
+
*
|
|
105
|
+
* @param options - The cache key options
|
|
106
|
+
* @returns A 64-character hex hash string
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const key = createCacheKey({
|
|
111
|
+
* value: largeDocument,
|
|
112
|
+
* question: 'Is this appropriate?',
|
|
113
|
+
* provider: 'openai',
|
|
114
|
+
* model: 'gpt-4o-mini',
|
|
115
|
+
* });
|
|
116
|
+
* // Returns: "a8f4b2c1e9d3..." (64 chars)
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare function createCacheKey(options: CacheKeyOptions): string;
|
|
120
|
+
/**
|
|
121
|
+
* Get a cached result if available and not expired.
|
|
122
|
+
*
|
|
123
|
+
* @param key - The cache key
|
|
124
|
+
* @returns The cached result or undefined if not found/expired
|
|
125
|
+
*/
|
|
126
|
+
export declare function getCached(key: string): boolean | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* Store a result in the cache.
|
|
129
|
+
*
|
|
130
|
+
* @param key - The cache key
|
|
131
|
+
* @param result - The result to cache
|
|
132
|
+
*/
|
|
133
|
+
export declare function setCache(key: string, result: boolean): void;
|
|
134
|
+
/**
|
|
135
|
+
* Clear the entire cache.
|
|
136
|
+
*/
|
|
137
|
+
export declare function clearCache(): void;
|
|
138
|
+
/**
|
|
139
|
+
* Get the current cache size (for testing/debugging).
|
|
140
|
+
*/
|
|
141
|
+
export declare function getCacheSize(): number;
|
|
142
|
+
/**
|
|
143
|
+
* Options for the caching wrapper.
|
|
144
|
+
*/
|
|
145
|
+
export interface WithCacheOptions {
|
|
146
|
+
/** The AI provider type for cache key isolation */
|
|
147
|
+
providerType: string;
|
|
148
|
+
/** The model identifier for cache key isolation */
|
|
149
|
+
model: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Wrap an AI provider with caching.
|
|
153
|
+
*
|
|
154
|
+
* The cache is isolated by provider type and model to prevent collisions
|
|
155
|
+
* when multiple Echo instances use different AI configurations.
|
|
156
|
+
*
|
|
157
|
+
* @param provider - The AI provider to wrap
|
|
158
|
+
* @param options - Cache options including provider/model for key isolation
|
|
159
|
+
* @returns A caching wrapper around the provider
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* const provider = createOpenAIProvider(config);
|
|
164
|
+
* const cachedProvider = withCache(provider, {
|
|
165
|
+
* providerType: 'openai',
|
|
166
|
+
* model: 'gpt-4o-mini',
|
|
167
|
+
* });
|
|
168
|
+
*
|
|
169
|
+
* // First call hits the API
|
|
170
|
+
* const result1 = await cachedProvider.evaluate(value, question);
|
|
171
|
+
*
|
|
172
|
+
* // Second call with same inputs returns cached result
|
|
173
|
+
* const result2 = await cachedProvider.evaluate(value, question);
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export declare function withCache(provider: AIProvider, options: WithCacheOptions): AIProvider;
|
|
177
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai-judge/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D;AAiCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CA0DzE;AAyCD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUpE;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAclE;AAYD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,KAAK,EAAE,OAAO,CAAC;IACf,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAI/D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAW1D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAK3D;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,GAAG,UAAU,CA2BrF"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview AI Judge - LLM-based condition evaluation
|
|
3
|
+
*
|
|
4
|
+
* This module handles the #ai_judge operator which queries an LLM
|
|
5
|
+
* to evaluate boolean conditions.
|
|
6
|
+
*
|
|
7
|
+
* FEATURES:
|
|
8
|
+
* - Provider abstraction for different backends (OpenAI, Anthropic)
|
|
9
|
+
* - Automatic caching with TTL to avoid redundant API calls
|
|
10
|
+
* - Structured prompts for consistent yes/no answers
|
|
11
|
+
* - Graceful error handling
|
|
12
|
+
*
|
|
13
|
+
* API KEY CONFIGURATION:
|
|
14
|
+
* The API key can be provided in three ways (in priority order):
|
|
15
|
+
* 1. Programmatic: createEcho({ aiProvider: { apiKey: '...' } })
|
|
16
|
+
* 2. Environment: ECHO_API_KEY or OPENAI_API_KEY
|
|
17
|
+
* 3. Config file: echo.config.yaml (aiProvider.apiKey)
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from 'crypto';
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// OPENAI PROVIDER
|
|
22
|
+
// =============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* Create an OpenAI-based AI provider.
|
|
25
|
+
*
|
|
26
|
+
* @param config - Configuration with API key and model
|
|
27
|
+
* @returns AIProvider using OpenAI
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const provider = createOpenAIProvider({
|
|
32
|
+
* type: 'openai',
|
|
33
|
+
* apiKey: process.env.OPENAI_API_KEY,
|
|
34
|
+
* model: 'gpt-4o-mini',
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* const result = await provider.evaluate(
|
|
38
|
+
* 'This is a family-friendly movie.',
|
|
39
|
+
* 'Is this content appropriate for children?'
|
|
40
|
+
* );
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function createOpenAIProvider(config) {
|
|
44
|
+
const apiKey = config.apiKey;
|
|
45
|
+
const model = config.model ?? 'gpt-4o-mini';
|
|
46
|
+
const timeout = config.timeout ?? 30000;
|
|
47
|
+
if (!apiKey) {
|
|
48
|
+
throw new Error('OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it in config.');
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
async evaluate(value, question) {
|
|
52
|
+
const prompt = buildPrompt(value, question);
|
|
53
|
+
const messages = [
|
|
54
|
+
{
|
|
55
|
+
role: 'system',
|
|
56
|
+
content: 'You are a precise yes/no evaluator. Answer ONLY with "yes" or "no" (lowercase, no punctuation). Do not explain or elaborate.',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
role: 'user',
|
|
60
|
+
content: prompt,
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
try {
|
|
64
|
+
const response = await callOpenAI(apiKey, model, messages, timeout);
|
|
65
|
+
const answer = response.choices[0]?.message?.content?.trim().toLowerCase();
|
|
66
|
+
if (answer === 'yes') {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (answer === 'no') {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
// Unexpected response - try to interpret
|
|
73
|
+
if (answer?.includes('yes')) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if (answer?.includes('no')) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
// Default to false for ambiguous responses
|
|
80
|
+
console.warn(`AI Judge returned unexpected response: "${answer}". Defaulting to false.`);
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
// Re-throw with more context
|
|
85
|
+
if (error instanceof Error) {
|
|
86
|
+
throw new Error(`AI Judge evaluation failed: ${error.message}`);
|
|
87
|
+
}
|
|
88
|
+
throw new Error('AI Judge evaluation failed: Unknown error');
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Call the OpenAI Chat Completions API.
|
|
95
|
+
*/
|
|
96
|
+
async function callOpenAI(apiKey, model, messages, timeout) {
|
|
97
|
+
const controller = new AbortController();
|
|
98
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
99
|
+
try {
|
|
100
|
+
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: {
|
|
103
|
+
'Content-Type': 'application/json',
|
|
104
|
+
Authorization: `Bearer ${apiKey}`,
|
|
105
|
+
},
|
|
106
|
+
body: JSON.stringify({
|
|
107
|
+
model,
|
|
108
|
+
messages,
|
|
109
|
+
max_tokens: 10,
|
|
110
|
+
temperature: 0, // Deterministic responses
|
|
111
|
+
}),
|
|
112
|
+
signal: controller.signal,
|
|
113
|
+
});
|
|
114
|
+
if (!response.ok) {
|
|
115
|
+
const errorBody = await response.text();
|
|
116
|
+
throw new Error(`OpenAI API error (${response.status}): ${errorBody}`);
|
|
117
|
+
}
|
|
118
|
+
return (await response.json());
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
clearTimeout(timeoutId);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Build the prompt for the AI judge.
|
|
126
|
+
*
|
|
127
|
+
* The prompt is designed to get a clear yes/no answer.
|
|
128
|
+
*
|
|
129
|
+
* @param value - The value to evaluate
|
|
130
|
+
* @param question - The question to ask
|
|
131
|
+
* @returns Formatted prompt string
|
|
132
|
+
*/
|
|
133
|
+
export function buildPrompt(value, question) {
|
|
134
|
+
const valueStr = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
135
|
+
return `Given the following value:
|
|
136
|
+
---
|
|
137
|
+
${valueStr}
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
Answer with ONLY "yes" or "no":
|
|
141
|
+
${question}`;
|
|
142
|
+
}
|
|
143
|
+
// =============================================================================
|
|
144
|
+
// AI JUDGE FACTORY
|
|
145
|
+
// =============================================================================
|
|
146
|
+
/**
|
|
147
|
+
* Create an AI Judge instance with the given configuration.
|
|
148
|
+
*
|
|
149
|
+
* @param config - AI provider configuration
|
|
150
|
+
* @returns An AIProvider implementation
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* const judge = createAIJudge({
|
|
155
|
+
* type: 'openai',
|
|
156
|
+
* apiKey: process.env.OPENAI_API_KEY,
|
|
157
|
+
* });
|
|
158
|
+
*
|
|
159
|
+
* const isAppropriate = await judge.evaluate(content, 'Is this safe for work?');
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export function createAIJudge(config) {
|
|
163
|
+
switch (config.type) {
|
|
164
|
+
case 'openai':
|
|
165
|
+
return createOpenAIProvider(config);
|
|
166
|
+
case 'anthropic':
|
|
167
|
+
// TODO: Implement Anthropic provider
|
|
168
|
+
throw new Error('Anthropic provider not yet implemented. Use OpenAI for now.');
|
|
169
|
+
default:
|
|
170
|
+
throw new Error(`Unknown AI provider type: ${config.type}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// =============================================================================
|
|
174
|
+
// CACHING
|
|
175
|
+
// =============================================================================
|
|
176
|
+
/** Module-level cache for AI judge results */
|
|
177
|
+
const cache = new Map();
|
|
178
|
+
/** Cache TTL in milliseconds (5 minutes) */
|
|
179
|
+
const CACHE_TTL = 5 * 60 * 1000;
|
|
180
|
+
/**
|
|
181
|
+
* Create a cache key for an AI judge evaluation.
|
|
182
|
+
*
|
|
183
|
+
* Uses SHA-256 hashing to create a fixed-size key regardless of input size.
|
|
184
|
+
* This is critical because the value being evaluated can be extremely large
|
|
185
|
+
* (e.g., a 200K token document). Storing the raw value as a Map key would
|
|
186
|
+
* cause severe memory bloat.
|
|
187
|
+
*
|
|
188
|
+
* The hash includes provider and model to prevent cache collisions when
|
|
189
|
+
* multiple Echo instances use different AI configurations.
|
|
190
|
+
*
|
|
191
|
+
* @param options - The cache key options
|
|
192
|
+
* @returns A 64-character hex hash string
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* const key = createCacheKey({
|
|
197
|
+
* value: largeDocument,
|
|
198
|
+
* question: 'Is this appropriate?',
|
|
199
|
+
* provider: 'openai',
|
|
200
|
+
* model: 'gpt-4o-mini',
|
|
201
|
+
* });
|
|
202
|
+
* // Returns: "a8f4b2c1e9d3..." (64 chars)
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
export function createCacheKey(options) {
|
|
206
|
+
const { value, question, provider, model } = options;
|
|
207
|
+
const data = JSON.stringify({ value, question, provider, model });
|
|
208
|
+
return createHash('sha256').update(data).digest('hex');
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get a cached result if available and not expired.
|
|
212
|
+
*
|
|
213
|
+
* @param key - The cache key
|
|
214
|
+
* @returns The cached result or undefined if not found/expired
|
|
215
|
+
*/
|
|
216
|
+
export function getCached(key) {
|
|
217
|
+
const entry = cache.get(key);
|
|
218
|
+
if (!entry)
|
|
219
|
+
return undefined;
|
|
220
|
+
// Check if expired
|
|
221
|
+
if (Date.now() - entry.timestamp > CACHE_TTL) {
|
|
222
|
+
cache.delete(key);
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
return entry.result;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Store a result in the cache.
|
|
229
|
+
*
|
|
230
|
+
* @param key - The cache key
|
|
231
|
+
* @param result - The result to cache
|
|
232
|
+
*/
|
|
233
|
+
export function setCache(key, result) {
|
|
234
|
+
cache.set(key, {
|
|
235
|
+
result,
|
|
236
|
+
timestamp: Date.now(),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Clear the entire cache.
|
|
241
|
+
*/
|
|
242
|
+
export function clearCache() {
|
|
243
|
+
cache.clear();
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Get the current cache size (for testing/debugging).
|
|
247
|
+
*/
|
|
248
|
+
export function getCacheSize() {
|
|
249
|
+
return cache.size;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Wrap an AI provider with caching.
|
|
253
|
+
*
|
|
254
|
+
* The cache is isolated by provider type and model to prevent collisions
|
|
255
|
+
* when multiple Echo instances use different AI configurations.
|
|
256
|
+
*
|
|
257
|
+
* @param provider - The AI provider to wrap
|
|
258
|
+
* @param options - Cache options including provider/model for key isolation
|
|
259
|
+
* @returns A caching wrapper around the provider
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```typescript
|
|
263
|
+
* const provider = createOpenAIProvider(config);
|
|
264
|
+
* const cachedProvider = withCache(provider, {
|
|
265
|
+
* providerType: 'openai',
|
|
266
|
+
* model: 'gpt-4o-mini',
|
|
267
|
+
* });
|
|
268
|
+
*
|
|
269
|
+
* // First call hits the API
|
|
270
|
+
* const result1 = await cachedProvider.evaluate(value, question);
|
|
271
|
+
*
|
|
272
|
+
* // Second call with same inputs returns cached result
|
|
273
|
+
* const result2 = await cachedProvider.evaluate(value, question);
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
export function withCache(provider, options) {
|
|
277
|
+
const { providerType, model } = options;
|
|
278
|
+
return {
|
|
279
|
+
async evaluate(value, question) {
|
|
280
|
+
const key = createCacheKey({
|
|
281
|
+
value,
|
|
282
|
+
question,
|
|
283
|
+
provider: providerType,
|
|
284
|
+
model,
|
|
285
|
+
});
|
|
286
|
+
// Check cache first
|
|
287
|
+
const cached = getCached(key);
|
|
288
|
+
if (cached !== undefined) {
|
|
289
|
+
return cached;
|
|
290
|
+
}
|
|
291
|
+
// Call the provider
|
|
292
|
+
const result = await provider.evaluate(value, question);
|
|
293
|
+
// Cache the result
|
|
294
|
+
setCache(key, result);
|
|
295
|
+
return result;
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai-judge/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Echo Evaluator - Condition evaluation engine
|
|
3
|
+
*
|
|
4
|
+
* This file implements the evaluator for Echo DSL.
|
|
5
|
+
* The evaluator processes the AST and determines which nodes should be rendered
|
|
6
|
+
* based on the provided context and condition evaluation.
|
|
7
|
+
*
|
|
8
|
+
* KEY OPTIMIZATION: AI JUDGE PARALLELIZATION
|
|
9
|
+
* Before evaluating the AST, we:
|
|
10
|
+
* 1. Collect ALL #ai_judge conditions from the tree
|
|
11
|
+
* 2. Evaluate them in parallel using Promise.all
|
|
12
|
+
* 3. Cache the results
|
|
13
|
+
* 4. Use cached results during tree evaluation
|
|
14
|
+
*
|
|
15
|
+
* This prevents sequential blocking on AI calls.
|
|
16
|
+
*/
|
|
17
|
+
import type { ASTNode, ConditionalNode, ConditionExpr, EchoConfig, OperatorDefinition } from '../types.js';
|
|
18
|
+
/**
|
|
19
|
+
* Evaluation context containing variables and resolved AI judges.
|
|
20
|
+
*/
|
|
21
|
+
export interface EvaluationContext {
|
|
22
|
+
/** Variables from user context */
|
|
23
|
+
variables: Record<string, unknown>;
|
|
24
|
+
/** Pre-resolved AI judge results (from parallel evaluation) */
|
|
25
|
+
aiJudgeResults: Map<string, boolean>;
|
|
26
|
+
/** Configuration */
|
|
27
|
+
config: EchoConfig;
|
|
28
|
+
/** Registered sections (for [#INCLUDE]) */
|
|
29
|
+
sections: Map<string, ASTNode[]>;
|
|
30
|
+
/** Custom operators (plugins) */
|
|
31
|
+
operators: Map<string, OperatorDefinition>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Result of evaluating a node.
|
|
35
|
+
*/
|
|
36
|
+
export interface EvaluatedNode {
|
|
37
|
+
/** The original node */
|
|
38
|
+
node: ASTNode;
|
|
39
|
+
/** Whether this node should be rendered */
|
|
40
|
+
shouldRender: boolean;
|
|
41
|
+
/** For conditionals: the branch to render */
|
|
42
|
+
selectedBranch?: ASTNode[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Options for variable resolution.
|
|
46
|
+
*/
|
|
47
|
+
export interface ResolveVariableOptions {
|
|
48
|
+
/** Whether to throw on malformed paths (default: false) */
|
|
49
|
+
strict?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a variable path from context.
|
|
53
|
+
*
|
|
54
|
+
* Supports:
|
|
55
|
+
* - Simple: "name" -> context.name
|
|
56
|
+
* - Nested: "user.name" -> context.user.name
|
|
57
|
+
* - Array: "items[0]" -> context.items[0]
|
|
58
|
+
* - Mixed: "users[0].name" -> context.users[0].name
|
|
59
|
+
*
|
|
60
|
+
* @param path - The variable path
|
|
61
|
+
* @param context - The context object
|
|
62
|
+
* @param options - Resolution options
|
|
63
|
+
* @returns The resolved value or undefined
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const context = { user: { name: 'Alice' }, items: [1, 2, 3] };
|
|
68
|
+
* resolveVariable('user.name', context); // 'Alice'
|
|
69
|
+
* resolveVariable('items[0]', context); // 1
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function resolveVariable(path: string, context: Record<string, unknown>, options?: ResolveVariableOptions): unknown;
|
|
73
|
+
/**
|
|
74
|
+
* Evaluate a condition expression.
|
|
75
|
+
*
|
|
76
|
+
* @param condition - The condition to evaluate
|
|
77
|
+
* @param ctx - The evaluation context
|
|
78
|
+
* @returns true if condition is satisfied
|
|
79
|
+
*/
|
|
80
|
+
export declare function evaluateCondition(condition: ConditionExpr, ctx: EvaluationContext): Promise<boolean>;
|
|
81
|
+
/**
|
|
82
|
+
* Pre-evaluate all AI judge conditions in parallel.
|
|
83
|
+
*
|
|
84
|
+
* This is the key optimization for performance.
|
|
85
|
+
* Call this before evaluating the AST to pre-resolve all AI conditions.
|
|
86
|
+
*
|
|
87
|
+
* @param ast - The AST to scan for AI judges
|
|
88
|
+
* @param ctx - The evaluation context (will be mutated with results)
|
|
89
|
+
*/
|
|
90
|
+
export declare function preEvaluateAiJudges(ast: ASTNode[], ctx: EvaluationContext): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Evaluate a conditional node and determine which branch to render.
|
|
93
|
+
*
|
|
94
|
+
* @param node - The conditional node
|
|
95
|
+
* @param ctx - The evaluation context
|
|
96
|
+
* @returns The nodes to render (empty if condition is false with no else)
|
|
97
|
+
*/
|
|
98
|
+
export declare function evaluateConditional(node: ConditionalNode, ctx: EvaluationContext): Promise<ASTNode[]>;
|
|
99
|
+
/**
|
|
100
|
+
* Evaluate an AST with the given context.
|
|
101
|
+
*
|
|
102
|
+
* This is the main entry point for AST evaluation. It:
|
|
103
|
+
* 1. Collects section definitions (first pass)
|
|
104
|
+
* 2. Pre-evaluates AI judge conditions in parallel
|
|
105
|
+
* 3. Evaluates the AST and selects conditional branches
|
|
106
|
+
* 4. Returns a flattened AST ready for rendering
|
|
107
|
+
*
|
|
108
|
+
* @param ast - The AST to evaluate
|
|
109
|
+
* @param context - Variable context
|
|
110
|
+
* @param config - Echo configuration
|
|
111
|
+
* @param operators - Custom operators (from plugins)
|
|
112
|
+
* @returns Evaluated AST and section map
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* const result = await evaluate(ast, { name: 'Alice', age: 25 });
|
|
117
|
+
* console.log(result.ast); // Flattened, evaluated AST
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export declare function evaluate(ast: ASTNode[], context: Record<string, unknown>, config?: EchoConfig, operators?: Map<string, OperatorDefinition>): Promise<{
|
|
121
|
+
ast: ASTNode[];
|
|
122
|
+
sections: Map<string, ASTNode[]>;
|
|
123
|
+
}>;
|
|
124
|
+
/**
|
|
125
|
+
* Create an evaluation context manually.
|
|
126
|
+
* Useful for advanced use cases where you need more control.
|
|
127
|
+
*
|
|
128
|
+
* @param options - Context options
|
|
129
|
+
* @returns A new EvaluationContext
|
|
130
|
+
*/
|
|
131
|
+
export declare function createEvaluationContext(options: {
|
|
132
|
+
variables: Record<string, unknown>;
|
|
133
|
+
config?: EchoConfig;
|
|
134
|
+
operators?: Map<string, OperatorDefinition>;
|
|
135
|
+
}): EvaluationContext;
|
|
136
|
+
//# sourceMappingURL=evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/evaluator/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EAGf,aAAa,EACb,UAAU,EACV,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAQrB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,+DAA+D;IAC/D,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,oBAAoB;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACjC,iCAAiC;IACjC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,wBAAwB;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,2CAA2C;IAC3C,YAAY,EAAE,OAAO,CAAC;IACtB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;CAC5B;AAMD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAiDT;AAqDD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,aAAa,EACxB,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,OAAO,CAAC,CAwClB;AAiBD;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EAAE,EACd,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAMD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,OAAO,EAAE,CAAC,CAqBpB;AA+HD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,OAAO,EAAE,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,GAAE,UAAe,EACvB,SAAS,GAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAa,GACrD,OAAO,CAAC;IAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC,CAoB/D;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC7C,GAAG,iBAAiB,CAQpB"}
|