hedgequantx 2.9.23 → 2.9.26
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/package.json
CHANGED
|
@@ -334,16 +334,25 @@ const drawConnectionTest = async (agents, boxWidth, clearWithBanner) => {
|
|
|
334
334
|
|
|
335
335
|
const W = boxWidth - 2;
|
|
336
336
|
|
|
337
|
-
// Show loading state with spinner inside closed box
|
|
337
|
+
// Show loading state with spinner inside closed box (centered vertically)
|
|
338
338
|
clearWithBanner();
|
|
339
339
|
console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
|
|
340
340
|
console.log(chalk.cyan('║') + chalk.yellow.bold(centerText('AI AGENTS CONNECTION TEST', W)) + chalk.cyan('║'));
|
|
341
341
|
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
342
342
|
|
|
343
|
+
// Empty lines for vertical centering (top)
|
|
344
|
+
console.log(chalk.cyan('║') + ' '.repeat(W) + chalk.cyan('║'));
|
|
345
|
+
console.log(chalk.cyan('║') + ' '.repeat(W) + chalk.cyan('║'));
|
|
346
|
+
console.log(chalk.cyan('║') + ' '.repeat(W) + chalk.cyan('║'));
|
|
347
|
+
|
|
343
348
|
// Centered spinner text inside box
|
|
344
349
|
const spinnerText = 'Testing connections...';
|
|
345
350
|
const paddedText = centerText(spinnerText, W);
|
|
346
351
|
console.log(chalk.cyan('║') + chalk.yellow(paddedText) + chalk.cyan('║'));
|
|
352
|
+
|
|
353
|
+
// Empty lines for vertical centering (bottom)
|
|
354
|
+
console.log(chalk.cyan('║') + ' '.repeat(W) + chalk.cyan('║'));
|
|
355
|
+
console.log(chalk.cyan('║') + ' '.repeat(W) + chalk.cyan('║'));
|
|
347
356
|
console.log(chalk.cyan('║') + ' '.repeat(W) + chalk.cyan('║'));
|
|
348
357
|
console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
|
|
349
358
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const cliproxy = require('../cliproxy');
|
|
13
|
-
const
|
|
13
|
+
const { extractJSON } = require('./parser');
|
|
14
14
|
|
|
15
15
|
/** Test prompt to verify agent understands directive format */
|
|
16
16
|
const TEST_PROMPT = `You are being tested. Respond ONLY with this exact JSON, nothing else:
|
|
@@ -161,6 +161,7 @@ const testAgentConnection = async (agent) => {
|
|
|
161
161
|
|
|
162
162
|
/**
|
|
163
163
|
* Validate that response matches expected JSON format
|
|
164
|
+
* Uses extractJSON from parser.js to handle MiniMax <think> tags and other formats
|
|
164
165
|
* @param {string} content - Response content from agent
|
|
165
166
|
* @returns {Object} { valid, error }
|
|
166
167
|
*/
|
|
@@ -169,53 +170,40 @@ const validateResponseFormat = (content) => {
|
|
|
169
170
|
return { valid: false, error: 'Empty response' };
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Check required fields
|
|
190
|
-
if (!json.decision) {
|
|
191
|
-
return { valid: false, error: 'Missing "decision" field' };
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (json.confidence === undefined) {
|
|
195
|
-
return { valid: false, error: 'Missing "confidence" field' };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (!json.reason) {
|
|
199
|
-
return { valid: false, error: 'Missing "reason" field' };
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Validate decision value
|
|
203
|
-
const validDecisions = ['approve', 'reject', 'modify'];
|
|
204
|
-
if (!validDecisions.includes(json.decision)) {
|
|
205
|
-
return { valid: false, error: `Invalid decision: ${json.decision}` };
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Validate confidence is number 0-100
|
|
209
|
-
const conf = Number(json.confidence);
|
|
210
|
-
if (isNaN(conf) || conf < 0 || conf > 100) {
|
|
211
|
-
return { valid: false, error: `Invalid confidence: ${json.confidence}` };
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return { valid: true, error: null };
|
|
215
|
-
|
|
216
|
-
} catch (error) {
|
|
217
|
-
return { valid: false, error: `Parse error: ${error.message}` };
|
|
173
|
+
// Use robust JSON extraction from parser.js
|
|
174
|
+
// Handles: direct JSON, markdown code blocks, JSON with extra text (MiniMax <think> tags)
|
|
175
|
+
const json = extractJSON(content);
|
|
176
|
+
|
|
177
|
+
if (!json) {
|
|
178
|
+
return { valid: false, error: 'No valid JSON found in response' };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Check required fields
|
|
182
|
+
if (!json.decision) {
|
|
183
|
+
return { valid: false, error: 'Missing "decision" field' };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (json.confidence === undefined) {
|
|
187
|
+
return { valid: false, error: 'Missing "confidence" field' };
|
|
218
188
|
}
|
|
189
|
+
|
|
190
|
+
if (!json.reason) {
|
|
191
|
+
return { valid: false, error: 'Missing "reason" field' };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Validate decision value
|
|
195
|
+
const validDecisions = ['approve', 'reject', 'modify'];
|
|
196
|
+
if (!validDecisions.includes(json.decision)) {
|
|
197
|
+
return { valid: false, error: `Invalid decision: ${json.decision}` };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Validate confidence is number 0-100
|
|
201
|
+
const conf = Number(json.confidence);
|
|
202
|
+
if (isNaN(conf) || conf < 0 || conf > 100) {
|
|
203
|
+
return { valid: false, error: `Invalid confidence: ${json.confidence}` };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return { valid: true, error: null };
|
|
219
207
|
};
|
|
220
208
|
|
|
221
209
|
/**
|
|
@@ -338,7 +326,13 @@ const formatPreflightResults = (results, boxWidth) => {
|
|
|
338
326
|
lines.push(dottedLine('Format', chalk.green('✓ VALID'), 9));
|
|
339
327
|
} else {
|
|
340
328
|
lines.push(dottedLine('Connection', chalk.red('✗ FAILED'), 9));
|
|
341
|
-
|
|
329
|
+
// Truncate error message to fit in box
|
|
330
|
+
const maxErrorLen = W - 16; // Account for " Error: " prefix
|
|
331
|
+
let errorMsg = agent.error || 'Unknown error';
|
|
332
|
+
if (errorMsg.length > maxErrorLen) {
|
|
333
|
+
errorMsg = errorMsg.substring(0, maxErrorLen - 3) + '...';
|
|
334
|
+
}
|
|
335
|
+
lines.push(chalk.red(` Error: ${errorMsg}`));
|
|
342
336
|
}
|
|
343
337
|
|
|
344
338
|
lines.push('');
|
|
@@ -19,6 +19,7 @@ const DEFAULT_RESPONSE = {
|
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Extract JSON from a string that may contain markdown or extra text
|
|
22
|
+
* Handles MiniMax <think> tags, markdown code blocks, etc.
|
|
22
23
|
*/
|
|
23
24
|
const extractJSON = (text) => {
|
|
24
25
|
if (!text || typeof text !== 'string') return null;
|
|
@@ -36,8 +37,36 @@ const extractJSON = (text) => {
|
|
|
36
37
|
} catch (e) { /* continue */ }
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
//
|
|
40
|
-
|
|
40
|
+
// Remove <think>...</think> tags (MiniMax)
|
|
41
|
+
let cleaned = text.replace(/<think>[\s\S]*?<\/think>/gi, '').trim();
|
|
42
|
+
|
|
43
|
+
// Try to parse cleaned text
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(cleaned);
|
|
46
|
+
} catch (e) { /* continue */ }
|
|
47
|
+
|
|
48
|
+
// Find first complete JSON object using bracket matching
|
|
49
|
+
const startIdx = cleaned.indexOf('{');
|
|
50
|
+
if (startIdx !== -1) {
|
|
51
|
+
let depth = 0;
|
|
52
|
+
let endIdx = -1;
|
|
53
|
+
for (let i = startIdx; i < cleaned.length; i++) {
|
|
54
|
+
if (cleaned[i] === '{') depth++;
|
|
55
|
+
if (cleaned[i] === '}') depth--;
|
|
56
|
+
if (depth === 0) {
|
|
57
|
+
endIdx = i;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (endIdx !== -1) {
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(cleaned.substring(startIdx, endIdx + 1));
|
|
64
|
+
} catch (e) { /* continue */ }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Last resort: try to find JSON object pattern with "decision"
|
|
69
|
+
const jsonMatch = cleaned.match(/\{[^{}]*"decision"[^{}]*\}/);
|
|
41
70
|
if (jsonMatch) {
|
|
42
71
|
try {
|
|
43
72
|
return JSON.parse(jsonMatch[0]);
|