@luckydraw/cumulus 0.30.0 → 0.30.2
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,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intent Reviewer — adversarial quality gate for Write/Edit tool calls.
|
|
3
|
+
*
|
|
4
|
+
* Intercepts Write/Edit results, compares stated intent vs actual execution
|
|
5
|
+
* using GLM-5 via HuggingFace, and either passes or rejects with actionable feedback.
|
|
6
|
+
* After 3 failures on the same task+file, escalates to the user.
|
|
7
|
+
*/
|
|
8
|
+
export interface ReviewVerdict {
|
|
9
|
+
verdict: 'pass' | 'provisional_pass' | 'fail';
|
|
10
|
+
score: number;
|
|
11
|
+
claims: Array<{
|
|
12
|
+
claim: string;
|
|
13
|
+
finding: string;
|
|
14
|
+
result: 'true' | 'false' | 'partially_false';
|
|
15
|
+
}>;
|
|
16
|
+
limitations: string;
|
|
17
|
+
feedback: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ReviewInput {
|
|
20
|
+
intent: string;
|
|
21
|
+
execution: {
|
|
22
|
+
type: 'edit' | 'write';
|
|
23
|
+
file: string;
|
|
24
|
+
old?: string;
|
|
25
|
+
new_content: string;
|
|
26
|
+
};
|
|
27
|
+
taskContext?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ReviewLog {
|
|
30
|
+
threadId: string;
|
|
31
|
+
model: string;
|
|
32
|
+
toolName: string;
|
|
33
|
+
filePath: string;
|
|
34
|
+
verdict: 'pass' | 'provisional_pass' | 'fail' | 'skipped' | 'timeout' | 'error';
|
|
35
|
+
score: number;
|
|
36
|
+
attempt: number;
|
|
37
|
+
latencyMs: number;
|
|
38
|
+
timestamp: number;
|
|
39
|
+
}
|
|
40
|
+
export declare function shouldReview(toolName: string, params: Record<string, unknown>): boolean;
|
|
41
|
+
interface MessageLike {
|
|
42
|
+
role: string;
|
|
43
|
+
content: string | Array<{
|
|
44
|
+
type: string;
|
|
45
|
+
text?: string;
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Extract intent from the last assistant message.
|
|
50
|
+
* Priority: <thinking> > active <todo> item > plain text.
|
|
51
|
+
*/
|
|
52
|
+
export declare function extractIntent(messages: MessageLike[]): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Get the currently-active todo text (first [ ] item in last <todo> block).
|
|
55
|
+
* Used for failure counter keys and reset detection.
|
|
56
|
+
*/
|
|
57
|
+
export declare function getActiveTodoText(messages: MessageLike[]): string | null;
|
|
58
|
+
export declare class IntentReviewer {
|
|
59
|
+
private hfApiKey;
|
|
60
|
+
private states;
|
|
61
|
+
private reviewLogs;
|
|
62
|
+
constructor(hfApiKey: string);
|
|
63
|
+
/**
|
|
64
|
+
* Get or create per-thread review state.
|
|
65
|
+
*/
|
|
66
|
+
private getState;
|
|
67
|
+
/**
|
|
68
|
+
* Reset failure counters when user sends a new message.
|
|
69
|
+
*/
|
|
70
|
+
resetOnNewUserMessage(threadId: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Check if active todo changed (reset counters for affected files).
|
|
73
|
+
*/
|
|
74
|
+
private checkTodoReset;
|
|
75
|
+
/**
|
|
76
|
+
* Evaluate a Write/Edit execution against stated intent.
|
|
77
|
+
* Returns the modified tool result (pass-through, annotated, or error).
|
|
78
|
+
*/
|
|
79
|
+
evaluate(threadId: string, model: string, toolName: string, params: Record<string, unknown>, toolResult: string, messages: MessageLike[]): Promise<{
|
|
80
|
+
output: string;
|
|
81
|
+
isError: boolean;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* Call GLM-5 via HuggingFace to evaluate intent vs execution.
|
|
85
|
+
*/
|
|
86
|
+
private callReviewModel;
|
|
87
|
+
/**
|
|
88
|
+
* Log a review for analytics.
|
|
89
|
+
*/
|
|
90
|
+
private logReview;
|
|
91
|
+
/**
|
|
92
|
+
* Get review statistics for analytics.
|
|
93
|
+
*/
|
|
94
|
+
getStats(): {
|
|
95
|
+
total: number;
|
|
96
|
+
byVerdict: Record<string, number>;
|
|
97
|
+
avgLatencyMs: number;
|
|
98
|
+
p95LatencyMs: number;
|
|
99
|
+
p99LatencyMs: number;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export {};
|
|
103
|
+
//# sourceMappingURL=intent-reviewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent-reviewer.d.ts","sourceRoot":"","sources":["../../src/lib/intent-reviewer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,MAAM,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,iBAAiB,CAAA;KAAE,CAAC,CAAC;IAChG,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AA2CD,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAmBT;AAID,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,GAAG,IAAI,CAmDpE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,GAAG,IAAI,CAyBxE;AAID,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,UAAU,CAAmB;gBAEzB,QAAQ,EAAE,MAAM;IAI5B;;OAEG;IACH,OAAO,CAAC,QAAQ;IAWhB;;OAEG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ7C;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;;OAGG;IACG,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,WAAW,EAAE,GACtB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAiHhD;;OAEG;YACW,eAAe;IA8D7B;;OAEG;IACH,OAAO,CAAC,SAAS;IAmCjB;;OAEG;IACH,QAAQ,IAAI;QACV,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB;CAiBF"}
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intent Reviewer — adversarial quality gate for Write/Edit tool calls.
|
|
3
|
+
*
|
|
4
|
+
* Intercepts Write/Edit results, compares stated intent vs actual execution
|
|
5
|
+
* using GLM-5 via HuggingFace, and either passes or rejects with actionable feedback.
|
|
6
|
+
* After 3 failures on the same task+file, escalates to the user.
|
|
7
|
+
*/
|
|
8
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
9
|
+
const REVIEW_MODEL = 'zai-org/GLM-5';
|
|
10
|
+
const REVIEW_TIMEOUT_MS = 5_000; // GLM-5 via HF is slower than Haiku
|
|
11
|
+
const MAX_STRIKES = 3;
|
|
12
|
+
const HF_API_URL = 'https://router.huggingface.co/v1/chat/completions';
|
|
13
|
+
const REVIEWER_SYSTEM_PROMPT = `You are an Intent Reviewer. Your job is to DISPROVE that the output matches the stated intent. Assume the output is wrong until proven otherwise.
|
|
14
|
+
|
|
15
|
+
## What You Receive
|
|
16
|
+
- INTENT: What was planned (from <thinking>, <todo>, or surrounding text)
|
|
17
|
+
- EXECUTION: What was actually written (the diff or file content)
|
|
18
|
+
- TASK CONTEXT: The user's original request (if available)
|
|
19
|
+
|
|
20
|
+
For each claim in the intent, challenge it against the literal code. Does the implementation match both the letter and spirit of the claim?
|
|
21
|
+
|
|
22
|
+
## What You Cannot Evaluate
|
|
23
|
+
Subjective quality (fun, beautiful, engaging) is beyond your scope. State this limitation explicitly. Give a provisional pass when all verifiable claims check out but subjective assessment is needed.
|
|
24
|
+
|
|
25
|
+
## Response Format
|
|
26
|
+
Respond with ONLY valid JSON (no markdown fencing, no extra text):
|
|
27
|
+
{
|
|
28
|
+
"verdict": "pass" | "provisional_pass" | "fail",
|
|
29
|
+
"score": 0-10,
|
|
30
|
+
"claims": [
|
|
31
|
+
{ "claim": "description of what was intended", "finding": "what was actually done", "result": "true" | "false" | "partially_false" }
|
|
32
|
+
],
|
|
33
|
+
"limitations": "any aspects you cannot evaluate",
|
|
34
|
+
"feedback": "specific actionable feedback if failing, empty string if passing"
|
|
35
|
+
}`;
|
|
36
|
+
// ─── Skip Logic ──────────────────────────────────────────────────────────────
|
|
37
|
+
const SKIP_EXTENSIONS = /\.(json|yml|yaml|toml|env|lock|md|txt|csv|log)$/i;
|
|
38
|
+
export function shouldReview(toolName, params) {
|
|
39
|
+
if (toolName !== 'Write' && toolName !== 'Edit')
|
|
40
|
+
return false;
|
|
41
|
+
const file = params.file_path || '';
|
|
42
|
+
if (SKIP_EXTENSIONS.test(file))
|
|
43
|
+
return false;
|
|
44
|
+
// Skip tiny edits (< 5 lines changed)
|
|
45
|
+
if (params.old_string && params.new_string) {
|
|
46
|
+
const oldLines = params.old_string.split('\n').length;
|
|
47
|
+
const newLines = params.new_string.split('\n').length;
|
|
48
|
+
if (Math.max(oldLines, newLines) < 5)
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
// Skip tiny new files (< 20 lines)
|
|
52
|
+
if (toolName === 'Write' && params.content) {
|
|
53
|
+
if (params.content.split('\n').length < 20)
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Extract intent from the last assistant message.
|
|
60
|
+
* Priority: <thinking> > active <todo> item > plain text.
|
|
61
|
+
*/
|
|
62
|
+
export function extractIntent(messages) {
|
|
63
|
+
// Walk backwards to find last assistant message
|
|
64
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
65
|
+
const msg = messages[i];
|
|
66
|
+
if (msg.role !== 'assistant')
|
|
67
|
+
continue;
|
|
68
|
+
const text = typeof msg.content === 'string'
|
|
69
|
+
? msg.content
|
|
70
|
+
: msg.content
|
|
71
|
+
.filter(b => b.type === 'text' && b.text)
|
|
72
|
+
.map(b => b.text)
|
|
73
|
+
.join('\n');
|
|
74
|
+
if (!text)
|
|
75
|
+
continue;
|
|
76
|
+
const parts = [];
|
|
77
|
+
// Extract <thinking> block
|
|
78
|
+
const thinkingMatch = text.match(/<thinking>([\s\S]*?)<\/thinking>/);
|
|
79
|
+
if (thinkingMatch) {
|
|
80
|
+
parts.push(`THINKING: ${thinkingMatch[1].trim()}`);
|
|
81
|
+
}
|
|
82
|
+
// Extract active <todo> item (first [ ] in last <todo> block)
|
|
83
|
+
const todoBlocks = [...text.matchAll(/<todo>([\s\S]*?)<\/todo>/g)];
|
|
84
|
+
if (todoBlocks.length > 0) {
|
|
85
|
+
const lastTodo = todoBlocks[todoBlocks.length - 1][1];
|
|
86
|
+
const activeItem = lastTodo
|
|
87
|
+
.split('\n')
|
|
88
|
+
.find(line => line.match(/^[-\s]*\[ \]/));
|
|
89
|
+
if (activeItem) {
|
|
90
|
+
parts.push(`ACTIVE TODO: ${activeItem.replace(/^[-\s]*\[ \]\s*/, '').trim()}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Extract plain text (non-tag content)
|
|
94
|
+
const plainText = text
|
|
95
|
+
.replace(/<thinking>[\s\S]*?<\/thinking>/g, '')
|
|
96
|
+
.replace(/<todo>[\s\S]*?<\/todo>/g, '')
|
|
97
|
+
.trim();
|
|
98
|
+
if (plainText) {
|
|
99
|
+
parts.push(`TEXT: ${plainText.substring(0, 500)}`);
|
|
100
|
+
}
|
|
101
|
+
if (parts.length > 0) {
|
|
102
|
+
return parts.join('\n\n');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get the currently-active todo text (first [ ] item in last <todo> block).
|
|
109
|
+
* Used for failure counter keys and reset detection.
|
|
110
|
+
*/
|
|
111
|
+
export function getActiveTodoText(messages) {
|
|
112
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
113
|
+
const msg = messages[i];
|
|
114
|
+
if (msg.role !== 'assistant')
|
|
115
|
+
continue;
|
|
116
|
+
const text = typeof msg.content === 'string'
|
|
117
|
+
? msg.content
|
|
118
|
+
: msg.content
|
|
119
|
+
.filter(b => b.type === 'text' && b.text)
|
|
120
|
+
.map(b => b.text)
|
|
121
|
+
.join('\n');
|
|
122
|
+
const todoBlocks = [...text.matchAll(/<todo>([\s\S]*?)<\/todo>/g)];
|
|
123
|
+
if (todoBlocks.length > 0) {
|
|
124
|
+
const lastTodo = todoBlocks[todoBlocks.length - 1][1];
|
|
125
|
+
const activeItem = lastTodo
|
|
126
|
+
.split('\n')
|
|
127
|
+
.find(line => line.match(/^[-\s]*\[ \]/));
|
|
128
|
+
if (activeItem) {
|
|
129
|
+
return activeItem.replace(/^[-\s]*\[ \]\s*/, '').trim();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
// ─── Intent Reviewer ─────────────────────────────────────────────────────────
|
|
136
|
+
export class IntentReviewer {
|
|
137
|
+
hfApiKey;
|
|
138
|
+
states = new Map();
|
|
139
|
+
reviewLogs = [];
|
|
140
|
+
constructor(hfApiKey) {
|
|
141
|
+
this.hfApiKey = hfApiKey;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get or create per-thread review state.
|
|
145
|
+
*/
|
|
146
|
+
getState(threadId) {
|
|
147
|
+
if (!this.states.has(threadId)) {
|
|
148
|
+
this.states.set(threadId, {
|
|
149
|
+
failureCounts: new Map(),
|
|
150
|
+
feedbackHistory: new Map(),
|
|
151
|
+
lastActiveTodo: null,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return this.states.get(threadId);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Reset failure counters when user sends a new message.
|
|
158
|
+
*/
|
|
159
|
+
resetOnNewUserMessage(threadId) {
|
|
160
|
+
const state = this.states.get(threadId);
|
|
161
|
+
if (state) {
|
|
162
|
+
state.failureCounts.clear();
|
|
163
|
+
state.feedbackHistory.clear();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Check if active todo changed (reset counters for affected files).
|
|
168
|
+
*/
|
|
169
|
+
checkTodoReset(threadId, currentTodo) {
|
|
170
|
+
const state = this.getState(threadId);
|
|
171
|
+
if (currentTodo && state.lastActiveTodo && currentTodo !== state.lastActiveTodo) {
|
|
172
|
+
// Active todo changed — reset all counters
|
|
173
|
+
state.failureCounts.clear();
|
|
174
|
+
state.feedbackHistory.clear();
|
|
175
|
+
}
|
|
176
|
+
state.lastActiveTodo = currentTodo;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Evaluate a Write/Edit execution against stated intent.
|
|
180
|
+
* Returns the modified tool result (pass-through, annotated, or error).
|
|
181
|
+
*/
|
|
182
|
+
async evaluate(threadId, model, toolName, params, toolResult, messages) {
|
|
183
|
+
const filePath = params.file_path || 'unknown';
|
|
184
|
+
const activeTodo = getActiveTodoText(messages);
|
|
185
|
+
this.checkTodoReset(threadId, activeTodo);
|
|
186
|
+
// Extract intent
|
|
187
|
+
const intent = extractIntent(messages);
|
|
188
|
+
if (!intent) {
|
|
189
|
+
this.logReview(threadId, model, toolName, filePath, 'skipped', 0, 0, 0);
|
|
190
|
+
return { output: toolResult, isError: false };
|
|
191
|
+
}
|
|
192
|
+
// Build execution description
|
|
193
|
+
const execution = toolName === 'Edit'
|
|
194
|
+
? {
|
|
195
|
+
type: 'edit',
|
|
196
|
+
file: filePath,
|
|
197
|
+
old: params.old_string,
|
|
198
|
+
new_content: params.new_string,
|
|
199
|
+
}
|
|
200
|
+
: {
|
|
201
|
+
type: 'write',
|
|
202
|
+
file: filePath,
|
|
203
|
+
new_content: params.content,
|
|
204
|
+
};
|
|
205
|
+
// Truncate large content for the review (keep it fast)
|
|
206
|
+
const maxContentChars = 3000;
|
|
207
|
+
const executionDesc = execution.type === 'edit'
|
|
208
|
+
? `FILE: ${execution.file}\nOLD:\n${(execution.old || '').slice(0, maxContentChars)}\nNEW:\n${execution.new_content.slice(0, maxContentChars)}`
|
|
209
|
+
: `FILE: ${execution.file}\nCONTENT:\n${execution.new_content.slice(0, maxContentChars)}`;
|
|
210
|
+
// Call Haiku with timeout
|
|
211
|
+
const startTime = Date.now();
|
|
212
|
+
let verdict;
|
|
213
|
+
try {
|
|
214
|
+
verdict = await this.callReviewModel(intent, executionDesc, REVIEW_TIMEOUT_MS);
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
const latency = Date.now() - startTime;
|
|
218
|
+
const isTimeout = err.message?.includes('timeout');
|
|
219
|
+
this.logReview(threadId, model, toolName, filePath, isTimeout ? 'timeout' : 'error', 0, 0, latency);
|
|
220
|
+
console.warn(`[IntentReviewer] ${isTimeout ? 'TIMEOUT' : 'ERROR'} thread=${threadId} ` +
|
|
221
|
+
`latency=${latency}ms: ${err.message}`);
|
|
222
|
+
// Default to pass on infrastructure failure
|
|
223
|
+
return { output: toolResult, isError: false };
|
|
224
|
+
}
|
|
225
|
+
const latency = Date.now() - startTime;
|
|
226
|
+
const state = this.getState(threadId);
|
|
227
|
+
const key = `${activeTodo || 'no-todo'}:${filePath}`;
|
|
228
|
+
if (verdict.verdict === 'pass') {
|
|
229
|
+
this.logReview(threadId, model, toolName, filePath, 'pass', verdict.score, 0, latency);
|
|
230
|
+
return { output: toolResult, isError: false };
|
|
231
|
+
}
|
|
232
|
+
if (verdict.verdict === 'provisional_pass') {
|
|
233
|
+
this.logReview(threadId, model, toolName, filePath, 'provisional_pass', verdict.score, 0, latency);
|
|
234
|
+
const annotation = `\n\n[Intent Review: PROVISIONAL PASS — Score ${verdict.score}/10]\n` +
|
|
235
|
+
`Verified: ${verdict.claims.filter(c => c.result === 'true').map(c => c.claim).join(', ')}\n` +
|
|
236
|
+
`Unverifiable: ${verdict.limitations}`;
|
|
237
|
+
return { output: toolResult + annotation, isError: false };
|
|
238
|
+
}
|
|
239
|
+
// FAIL
|
|
240
|
+
const count = (state.failureCounts.get(key) || 0) + 1;
|
|
241
|
+
state.failureCounts.set(key, count);
|
|
242
|
+
if (!state.feedbackHistory.has(key)) {
|
|
243
|
+
state.feedbackHistory.set(key, []);
|
|
244
|
+
}
|
|
245
|
+
state.feedbackHistory.get(key).push(verdict.feedback);
|
|
246
|
+
this.logReview(threadId, model, toolName, filePath, 'fail', verdict.score, count, latency);
|
|
247
|
+
if (count >= MAX_STRIKES) {
|
|
248
|
+
const allFeedback = state.feedbackHistory.get(key) || [];
|
|
249
|
+
return {
|
|
250
|
+
output: `ESCALATION REQUIRED: You have failed this task ${MAX_STRIKES} times.\n\n` +
|
|
251
|
+
`Previous feedback:\n${allFeedback.map((f, i) => ` Attempt ${i + 1}: ${f}`).join('\n')}\n\n` +
|
|
252
|
+
`You MUST now:\n` +
|
|
253
|
+
`1. Stop attempting this task\n` +
|
|
254
|
+
`2. Explain the core difficulty to the user\n` +
|
|
255
|
+
`3. Suggest 2-3 ways to proceed\n\n` +
|
|
256
|
+
`Do NOT attempt another revision.`,
|
|
257
|
+
isError: true,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const failedClaims = verdict.claims
|
|
261
|
+
.filter(c => c.result !== 'true')
|
|
262
|
+
.map(c => `- "${c.claim}" → ${c.finding}`)
|
|
263
|
+
.join('\n');
|
|
264
|
+
return {
|
|
265
|
+
output: `REVISION REQUIRED (attempt ${count}/${MAX_STRIKES}): ${verdict.feedback}\n\n` +
|
|
266
|
+
`Claims that failed:\n${failedClaims}`,
|
|
267
|
+
isError: true,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Call GLM-5 via HuggingFace to evaluate intent vs execution.
|
|
272
|
+
*/
|
|
273
|
+
async callReviewModel(intent, execution, timeoutMs) {
|
|
274
|
+
const userMessage = `## INTENT\n${intent}\n\n## EXECUTION\n${execution}`;
|
|
275
|
+
const controller = new AbortController();
|
|
276
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
277
|
+
try {
|
|
278
|
+
const response = await fetch(HF_API_URL, {
|
|
279
|
+
method: 'POST',
|
|
280
|
+
headers: {
|
|
281
|
+
'Content-Type': 'application/json',
|
|
282
|
+
Authorization: `Bearer ${this.hfApiKey}`,
|
|
283
|
+
},
|
|
284
|
+
body: JSON.stringify({
|
|
285
|
+
model: REVIEW_MODEL,
|
|
286
|
+
max_tokens: 1024,
|
|
287
|
+
stream: false,
|
|
288
|
+
messages: [
|
|
289
|
+
{ role: 'system', content: REVIEWER_SYSTEM_PROMPT },
|
|
290
|
+
{ role: 'user', content: userMessage },
|
|
291
|
+
],
|
|
292
|
+
}),
|
|
293
|
+
signal: controller.signal,
|
|
294
|
+
});
|
|
295
|
+
clearTimeout(timer);
|
|
296
|
+
if (!response.ok) {
|
|
297
|
+
const body = await response.text().catch(() => '');
|
|
298
|
+
throw Object.assign(new Error(`HF API ${response.status}: ${body.slice(0, 200)}`), {
|
|
299
|
+
status: response.status,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
const json = (await response.json());
|
|
303
|
+
const text = json.choices?.[0]?.message?.content || '';
|
|
304
|
+
// Parse JSON — strip markdown fencing if present
|
|
305
|
+
const cleaned = text.replace(/^```(?:json)?\s*\n?/m, '').replace(/\n?```\s*$/m, '').trim();
|
|
306
|
+
const parsed = JSON.parse(cleaned);
|
|
307
|
+
// Validate required fields
|
|
308
|
+
if (!parsed.verdict || !['pass', 'provisional_pass', 'fail'].includes(parsed.verdict)) {
|
|
309
|
+
throw new Error(`Invalid verdict: ${parsed.verdict}`);
|
|
310
|
+
}
|
|
311
|
+
return parsed;
|
|
312
|
+
}
|
|
313
|
+
catch (err) {
|
|
314
|
+
clearTimeout(timer);
|
|
315
|
+
if (err.name === 'AbortError') {
|
|
316
|
+
throw new Error('Review timeout exceeded');
|
|
317
|
+
}
|
|
318
|
+
throw err;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Log a review for analytics.
|
|
323
|
+
*/
|
|
324
|
+
logReview(threadId, model, toolName, filePath, verdict, score, attempt, latencyMs) {
|
|
325
|
+
const entry = {
|
|
326
|
+
threadId,
|
|
327
|
+
model,
|
|
328
|
+
toolName,
|
|
329
|
+
filePath,
|
|
330
|
+
verdict,
|
|
331
|
+
score,
|
|
332
|
+
attempt,
|
|
333
|
+
latencyMs,
|
|
334
|
+
timestamp: Date.now(),
|
|
335
|
+
};
|
|
336
|
+
this.reviewLogs.push(entry);
|
|
337
|
+
// Keep only last 1000 entries in memory
|
|
338
|
+
if (this.reviewLogs.length > 1000) {
|
|
339
|
+
this.reviewLogs = this.reviewLogs.slice(-500);
|
|
340
|
+
}
|
|
341
|
+
console.log(`[IntentReviewer] thread=${threadId} tool=${toolName} file=${filePath.split('/').pop()} ` +
|
|
342
|
+
`verdict=${verdict} score=${score} attempt=${attempt} latency=${latencyMs}ms`);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Get review statistics for analytics.
|
|
346
|
+
*/
|
|
347
|
+
getStats() {
|
|
348
|
+
const total = this.reviewLogs.length;
|
|
349
|
+
const byVerdict = {};
|
|
350
|
+
const latencies = [];
|
|
351
|
+
for (const log of this.reviewLogs) {
|
|
352
|
+
byVerdict[log.verdict] = (byVerdict[log.verdict] || 0) + 1;
|
|
353
|
+
if (log.latencyMs > 0)
|
|
354
|
+
latencies.push(log.latencyMs);
|
|
355
|
+
}
|
|
356
|
+
latencies.sort((a, b) => a - b);
|
|
357
|
+
const avg = latencies.length > 0 ? latencies.reduce((a, b) => a + b, 0) / latencies.length : 0;
|
|
358
|
+
const p95 = latencies.length > 0 ? latencies[Math.floor(latencies.length * 0.95)] : 0;
|
|
359
|
+
const p99 = latencies.length > 0 ? latencies[Math.floor(latencies.length * 0.99)] : 0;
|
|
360
|
+
return { total, byVerdict, avgLatencyMs: Math.round(avg), p95LatencyMs: p95 ?? 0, p99LatencyMs: p99 ?? 0 };
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=intent-reviewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent-reviewer.js","sourceRoot":"","sources":["../../src/lib/intent-reviewer.ts"],"names":[],"mappings":"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"}
|