mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
Add tests and implement functionality for staged cascade search and LSP expansion
- Introduced a new JSON file for verbose output of the Codex Lens search results. - Added unit tests for binary search functionality in `test_stage1_binary_search_uses_chunk_lines.py`. - Implemented regression tests for staged cascade Stage 2 expansion depth in `test_staged_cascade_lsp_depth.py`. - Created unit tests for staged cascade Stage 2 realtime LSP graph expansion in `test_staged_cascade_realtime_lsp.py`. - Enhanced the ChainSearchEngine to respect configuration settings for staged LSP depth and improve search accuracy.
This commit is contained in:
@@ -439,6 +439,119 @@ export async function handleSystemRoutes(ctx: SystemRouteContext): Promise<boole
|
||||
return true;
|
||||
}
|
||||
|
||||
// API: Native OS folder selection dialog
|
||||
if (pathname === '/api/dialog/select-folder' && req.method === 'POST') {
|
||||
handlePostRequest(req, res, async (body) => {
|
||||
const { initialDir } = body as { initialDir?: string };
|
||||
const os = await import('os');
|
||||
const { execFile } = await import('child_process');
|
||||
const startDir = initialDir || os.homedir();
|
||||
|
||||
return new Promise<Record<string, unknown>>((resolve) => {
|
||||
if (process.platform === 'win32') {
|
||||
const script = `Add-Type -AssemblyName System.Windows.Forms; $d = New-Object System.Windows.Forms.FolderBrowserDialog; $d.SelectedPath = '${startDir.replace(/'/g, "''")}'; $d.ShowNewFolderButton = $true; if ($d.ShowDialog() -eq 'OK') { $d.SelectedPath }`;
|
||||
execFile('powershell', ['-NoProfile', '-Command', script],
|
||||
{ timeout: 120000 },
|
||||
(err, stdout) => {
|
||||
if (err || !stdout.trim()) {
|
||||
resolve({ cancelled: true });
|
||||
} else {
|
||||
resolve({ path: stdout.trim() });
|
||||
}
|
||||
}
|
||||
);
|
||||
} else if (process.platform === 'darwin') {
|
||||
const escapedDir = startDir.replace(/"/g, '\\"');
|
||||
const script = `POSIX path of (choose folder with prompt "Select Project Folder" default location POSIX file "${escapedDir}")`;
|
||||
execFile('osascript', ['-e', script],
|
||||
{ timeout: 120000 },
|
||||
(err, stdout) => {
|
||||
if (err || !stdout.trim()) {
|
||||
resolve({ cancelled: true });
|
||||
} else {
|
||||
resolve({ path: stdout.trim().replace(/\/$/, '') });
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// Linux: try zenity, fallback to kdialog
|
||||
execFile('zenity', ['--file-selection', '--directory', '--title=Select Project Folder', `--filename=${startDir}/`],
|
||||
{ timeout: 120000 },
|
||||
(err, stdout) => {
|
||||
if (err || !stdout.trim()) {
|
||||
execFile('kdialog', ['--getexistingdirectory', startDir, '--title', 'Select Project Folder'],
|
||||
{ timeout: 120000 },
|
||||
(err2, stdout2) => {
|
||||
resolve(err2 || !stdout2.trim() ? { cancelled: true } : { path: stdout2.trim() });
|
||||
}
|
||||
);
|
||||
} else {
|
||||
resolve({ path: stdout.trim() });
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// API: Native OS file selection dialog
|
||||
if (pathname === '/api/dialog/select-file' && req.method === 'POST') {
|
||||
handlePostRequest(req, res, async (body) => {
|
||||
const { initialDir } = body as { initialDir?: string };
|
||||
const os = await import('os');
|
||||
const { execFile } = await import('child_process');
|
||||
const startDir = initialDir || os.homedir();
|
||||
|
||||
return new Promise<Record<string, unknown>>((resolve) => {
|
||||
if (process.platform === 'win32') {
|
||||
const script = `Add-Type -AssemblyName System.Windows.Forms; $d = New-Object System.Windows.Forms.OpenFileDialog; $d.InitialDirectory = '${startDir.replace(/'/g, "''")}'; if ($d.ShowDialog() -eq 'OK') { $d.FileName }`;
|
||||
execFile('powershell', ['-NoProfile', '-Command', script],
|
||||
{ timeout: 120000 },
|
||||
(err, stdout) => {
|
||||
if (err || !stdout.trim()) {
|
||||
resolve({ cancelled: true });
|
||||
} else {
|
||||
resolve({ path: stdout.trim() });
|
||||
}
|
||||
}
|
||||
);
|
||||
} else if (process.platform === 'darwin') {
|
||||
const escapedDir = startDir.replace(/"/g, '\\"');
|
||||
const script = `POSIX path of (choose file with prompt "Select File" default location POSIX file "${escapedDir}")`;
|
||||
execFile('osascript', ['-e', script],
|
||||
{ timeout: 120000 },
|
||||
(err, stdout) => {
|
||||
if (err || !stdout.trim()) {
|
||||
resolve({ cancelled: true });
|
||||
} else {
|
||||
resolve({ path: stdout.trim() });
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
execFile('zenity', ['--file-selection', '--title=Select File', `--filename=${startDir}/`],
|
||||
{ timeout: 120000 },
|
||||
(err, stdout) => {
|
||||
if (err || !stdout.trim()) {
|
||||
execFile('kdialog', ['--getopenfilename', startDir, '--title', 'Select File'],
|
||||
{ timeout: 120000 },
|
||||
(err2, stdout2) => {
|
||||
resolve(err2 || !stdout2.trim() ? { cancelled: true } : { path: stdout2.trim() });
|
||||
}
|
||||
);
|
||||
} else {
|
||||
resolve({ path: stdout.trim() });
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// API: File dialog - list directory contents for file browser
|
||||
if (pathname === '/api/dialog/browse' && req.method === 'POST') {
|
||||
handlePostRequest(req, res, async (body) => {
|
||||
|
||||
@@ -551,15 +551,18 @@ export function handleMultiAnswer(compositeId: string, answers: QuestionAnswer[]
|
||||
* Automatically stops when the questionId is no longer in pendingQuestions (timeout cleanup).
|
||||
*/
|
||||
function startAnswerPolling(questionId: string, isComposite: boolean = false): void {
|
||||
const path = `/api/a2ui/answer?questionId=${encodeURIComponent(questionId)}&composite=${isComposite}`;
|
||||
const pollPath = `/api/a2ui/answer?questionId=${encodeURIComponent(questionId)}&composite=${isComposite}`;
|
||||
|
||||
console.error(`[A2UI-Poll] Starting polling for questionId=${questionId}, composite=${isComposite}, port=${DASHBOARD_PORT}`);
|
||||
|
||||
const poll = () => {
|
||||
// Stop if the question was already resolved or timed out
|
||||
if (!pendingQuestions.has(questionId)) {
|
||||
console.error(`[A2UI-Poll] Stopping: questionId=${questionId} no longer pending`);
|
||||
return;
|
||||
}
|
||||
|
||||
const req = http.get({ hostname: 'localhost', port: DASHBOARD_PORT, path }, (res) => {
|
||||
const req = http.get({ hostname: '127.0.0.1', port: DASHBOARD_PORT, path: pollPath }, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk: Buffer) => { data += chunk.toString(); });
|
||||
res.on('end', () => {
|
||||
@@ -571,23 +574,27 @@ function startAnswerPolling(questionId: string, isComposite: boolean = false): v
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(`[A2UI-Poll] Answer received for questionId=${questionId}:`, JSON.stringify(parsed).slice(0, 200));
|
||||
|
||||
if (isComposite && Array.isArray(parsed.answers)) {
|
||||
handleMultiAnswer(questionId, parsed.answers as QuestionAnswer[]);
|
||||
const ok = handleMultiAnswer(questionId, parsed.answers as QuestionAnswer[]);
|
||||
console.error(`[A2UI-Poll] handleMultiAnswer result: ${ok}`);
|
||||
} else if (!isComposite && parsed.answer) {
|
||||
handleAnswer(parsed.answer as QuestionAnswer);
|
||||
const ok = handleAnswer(parsed.answer as QuestionAnswer);
|
||||
console.error(`[A2UI-Poll] handleAnswer result: ${ok}`);
|
||||
} else {
|
||||
// Unexpected shape, keep polling
|
||||
console.error(`[A2UI-Poll] Unexpected response shape, keep polling`);
|
||||
setTimeout(poll, POLL_INTERVAL_MS);
|
||||
}
|
||||
} catch {
|
||||
// Parse error, keep polling
|
||||
} catch (e) {
|
||||
console.error(`[A2UI-Poll] Parse error:`, e);
|
||||
setTimeout(poll, POLL_INTERVAL_MS);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', () => {
|
||||
// Network error (Dashboard not reachable), keep trying
|
||||
req.on('error', (err) => {
|
||||
console.error(`[A2UI-Poll] Network error: ${err.message}`);
|
||||
if (pendingQuestions.has(questionId)) {
|
||||
setTimeout(poll, POLL_INTERVAL_MS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user