fix(extension): step_type mapping bug + diff_review handler refactor
- Separate read tools (file_permission) from write tools (code_edit) - write_to_file/replace_file_content now use AcknowledgeCascadeCodeEdit RPC - diff_review: 2-strategy approach (RPC first, openReviewChanges fallback) - Track modified_files and edit_step_indices in diff_review pending - known-issues: 3 new entries (pending accumulation, step_type bug, isDirty failure)
This commit is contained in:
@@ -1739,6 +1739,8 @@ function setupMonitor() {
|
||||
let wasRunning = false; // track RUNNING→IDLE transition for response capture
|
||||
let lastUserInputStepIdx = -1; // track user input for response matching
|
||||
let pendingModifiedFiles: string[] = []; // accumulate modified files during RUNNING
|
||||
let pendingModifiedFilePaths: string[] = []; // full paths for diff review
|
||||
let pendingEditStepIndices: number[] = []; // step indices for AcknowledgeCascadeCodeEdit
|
||||
let lastResponseCaptureStep = -1; // dedup: don't capture same response twice
|
||||
|
||||
setInterval(async () => {
|
||||
@@ -1884,6 +1886,8 @@ function setupMonitor() {
|
||||
const bn = tf.split(/[\\/]/).pop() || tf;
|
||||
if (!pendingModifiedFiles.includes(bn)) {
|
||||
pendingModifiedFiles.push(bn);
|
||||
pendingModifiedFilePaths.push(tf);
|
||||
pendingEditStepIndices.push(actualIdx);
|
||||
logToFile(`[DIFF-TRACK] + ${bn} (step ${actualIdx})`);
|
||||
}
|
||||
}
|
||||
@@ -2057,7 +2061,9 @@ function setupMonitor() {
|
||||
conversation_id: activeSessionId,
|
||||
command,
|
||||
description: `Step #${actualIndex} (${(oStep.type || '').replace('CORTEX_STEP_TYPE_', '')})`,
|
||||
step_type: ['view_file', 'list_dir', 'find_by_name', 'read_file', 'grep_search', 'replace_file_content', 'write_to_file', 'multi_replace_file_content'].includes(toolName) ? 'file_permission' : toolName,
|
||||
step_type: ['view_file', 'list_dir', 'find_by_name', 'read_file', 'grep_search'].includes(toolName) ? 'file_permission'
|
||||
: ['write_to_file', 'replace_file_content', 'multi_replace_file_content'].includes(toolName) ? 'code_edit'
|
||||
: toolName,
|
||||
step_index: actualIndex,
|
||||
source: 'step_probe_offset',
|
||||
});
|
||||
@@ -2118,7 +2124,9 @@ function setupMonitor() {
|
||||
conversation_id: activeSessionId,
|
||||
command,
|
||||
description,
|
||||
step_type: ['view_file', 'list_dir', 'find_by_name', 'read_file', 'grep_search', 'replace_file_content', 'write_to_file', 'multi_replace_file_content'].includes(toolName) ? 'file_permission' : toolName,
|
||||
step_type: ['view_file', 'list_dir', 'find_by_name', 'read_file', 'grep_search'].includes(toolName) ? 'file_permission'
|
||||
: ['write_to_file', 'replace_file_content', 'multi_replace_file_content'].includes(toolName) ? 'code_edit'
|
||||
: toolName,
|
||||
step_index: si,
|
||||
source: 'step_probe',
|
||||
});
|
||||
@@ -2406,8 +2414,12 @@ function setupMonitor() {
|
||||
{ text: 'Accept all', index: 0 },
|
||||
{ text: 'Reject all', index: 1 },
|
||||
],
|
||||
});
|
||||
modified_files: pendingModifiedFilePaths.slice(0, 20),
|
||||
edit_step_indices: pendingEditStepIndices.slice(0, 20),
|
||||
} as any);
|
||||
pendingModifiedFiles = []; // reset after notification
|
||||
pendingModifiedFilePaths = [];
|
||||
pendingEditStepIndices = [];
|
||||
}
|
||||
wasRunning = isRunning;
|
||||
} catch (e: any) {
|
||||
@@ -2556,36 +2568,94 @@ async function processResponseFile(filePath: string) {
|
||||
|
||||
const approved = resp.approved;
|
||||
|
||||
// ── diff_review: Accept all / Reject all via VS Code commands ──
|
||||
// ── diff_review: Accept all / Reject all ──
|
||||
if (pendingStepType === 'diff_review') {
|
||||
const btnIdx = resp.button_index ?? -1;
|
||||
const isAccept = btnIdx === 0 || (btnIdx === -1 && approved);
|
||||
const cmd = isAccept
|
||||
? 'antigravity.prioritized.agentAcceptAllInFile'
|
||||
: 'antigravity.prioritized.agentRejectAllInFile';
|
||||
logToFile(`[RESPONSE] diff_review → ${cmd} (btnIdx=${btnIdx})`);
|
||||
try {
|
||||
// Find dirty documents and focus each before executing
|
||||
const dirtyDocs = vscode.workspace.textDocuments.filter(d => d.isDirty);
|
||||
logToFile(`[RESPONSE] diff_review: ${dirtyDocs.length} dirty docs found`);
|
||||
if (dirtyDocs.length > 0) {
|
||||
for (const doc of dirtyDocs) {
|
||||
try {
|
||||
await vscode.window.showTextDocument(doc, { preview: false });
|
||||
await new Promise(r => setTimeout(r, 200)); // brief wait for focus
|
||||
await vscode.commands.executeCommand(cmd);
|
||||
logToFile(`[RESPONSE] diff_review: ${cmd} on ${doc.fileName.split(/[\\/]/).pop()} OK`);
|
||||
} catch (perFileErr: any) {
|
||||
logToFile(`[RESPONSE] diff_review per-file error: ${perFileErr.message?.substring(0, 80)}`);
|
||||
logToFile(`[RESPONSE] diff_review → ${isAccept ? 'ACCEPT' : 'REJECT'} (btnIdx=${btnIdx})`);
|
||||
|
||||
let diffReviewDone = false;
|
||||
const targetSession = sessionId || activeSessionId;
|
||||
|
||||
// ── Strategy 1: AcknowledgeCascadeCodeEdit RPC ──
|
||||
// Accept/reject all pending code edits via protocol (no UI interaction needed)
|
||||
if (sdk) {
|
||||
try {
|
||||
// Get tracked step indices from pending data (or use all recent edit steps)
|
||||
const trackedSteps: number[] = [];
|
||||
const pendingDir = path.join(bridgePath, 'pending');
|
||||
try {
|
||||
const pendingFile = path.join(pendingDir, `${resp.request_id}.json`);
|
||||
if (fs.existsSync(pendingFile)) {
|
||||
const pd = JSON.parse(fs.readFileSync(pendingFile, 'utf-8'));
|
||||
if (pd.edit_step_indices) trackedSteps.push(...pd.edit_step_indices);
|
||||
}
|
||||
} catch { }
|
||||
|
||||
// If no tracked steps, use the step_index from the pending
|
||||
if (trackedSteps.length === 0 && pendingStepIndex > 0) {
|
||||
trackedSteps.push(pendingStepIndex);
|
||||
}
|
||||
} else {
|
||||
// No dirty docs — try command anyway
|
||||
await vscode.commands.executeCommand(cmd);
|
||||
logToFile(`[RESPONSE] diff_review: no dirty docs, command executed anyway`);
|
||||
|
||||
logToFile(`[DIFF-REVIEW-RPC] AcknowledgeCascadeCodeEdit(session=${targetSession.substring(0, 8)}, accept=${isAccept}, steps=[${trackedSteps.join(',')}])`);
|
||||
const ackResult = await sdk.ls.rawRPC('AcknowledgeCascadeCodeEdit', {
|
||||
cascadeId: targetSession,
|
||||
accept: isAccept,
|
||||
...(trackedSteps.length > 0 ? { stepIndices: trackedSteps } : {}),
|
||||
});
|
||||
logToFile(`[DIFF-REVIEW-RPC] ✅ SUCCESS: ${JSON.stringify(ackResult).substring(0, 200)}`);
|
||||
diffReviewDone = true;
|
||||
} catch (rpcErr: any) {
|
||||
logToFile(`[DIFF-REVIEW-RPC] ❌ ${rpcErr.message.substring(0, 200)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Strategy 2: Open review panel + focus file + VS Code command ──
|
||||
if (!diffReviewDone) {
|
||||
try {
|
||||
// Step 2a: Open the Review Changes panel
|
||||
try {
|
||||
await vscode.commands.executeCommand('antigravity.openReviewChanges');
|
||||
logToFile(`[DIFF-REVIEW-CMD] openReviewChanges OK`);
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
} catch { }
|
||||
|
||||
// Step 2b: Find modified files from pending data
|
||||
let modifiedFiles: string[] = [];
|
||||
try {
|
||||
const pendingFile = path.join(bridgePath, 'pending', `${resp.request_id}.json`);
|
||||
if (fs.existsSync(pendingFile)) {
|
||||
const pd = JSON.parse(fs.readFileSync(pendingFile, 'utf-8'));
|
||||
if (pd.modified_files) modifiedFiles = pd.modified_files;
|
||||
}
|
||||
} catch { }
|
||||
|
||||
// Step 2c: Open and focus each modified file, then execute
|
||||
if (modifiedFiles.length > 0) {
|
||||
for (const filePath of modifiedFiles) {
|
||||
try {
|
||||
const uri = vscode.Uri.file(filePath);
|
||||
const doc = await vscode.workspace.openTextDocument(uri);
|
||||
await vscode.window.showTextDocument(doc, { preview: false });
|
||||
await new Promise(r => setTimeout(r, 300));
|
||||
await vscode.commands.executeCommand(cmd);
|
||||
logToFile(`[DIFF-REVIEW-CMD] ${cmd} on ${filePath.split(/[\\/]/).pop()} OK`);
|
||||
} catch (e: any) {
|
||||
logToFile(`[DIFF-REVIEW-CMD] per-file error on ${filePath}: ${e.message?.substring(0, 80)}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No file list — just execute command (best effort)
|
||||
await vscode.commands.executeCommand(cmd);
|
||||
logToFile(`[DIFF-REVIEW-CMD] ${cmd} executed (no file list)`);
|
||||
}
|
||||
diffReviewDone = true;
|
||||
} catch (cmdErr: any) {
|
||||
logToFile(`[DIFF-REVIEW-CMD] error: ${cmdErr.message}`);
|
||||
}
|
||||
} catch (cmdErr: any) {
|
||||
logToFile(`[RESPONSE] diff_review command error: ${cmdErr.message}`);
|
||||
}
|
||||
} else if (isDomObserver) {
|
||||
// DOM observer path: ALSO try RPC strategies (renderer click is unreliable)
|
||||
@@ -2904,20 +2974,22 @@ async function tryApprovalStrategies(approved: boolean, sessionId: string, stepT
|
||||
const typeLower = stepType.toLowerCase().replace('cortex_step_type_', '');
|
||||
let interactionPayload: Record<string, any> = {};
|
||||
|
||||
if (typeLower.includes('write_to_file') || typeLower.includes('propose_code') || typeLower.includes('write_cascade_edit')) {
|
||||
if (typeLower.includes('code_edit') || typeLower.includes('write_to_file') || typeLower.includes('propose_code') || typeLower.includes('write_cascade_edit')) {
|
||||
// CODE EDIT: Uses separate AcknowledgeCascadeCodeEdit RPC
|
||||
try {
|
||||
logToFile(`[APPROVAL-PROTO-ACK] AcknowledgeCascadeCodeEdit(cascadeId=${sessionId.substring(0,8)}, accept=true, stepIndices=[${effectiveStepIndex}])`);
|
||||
logToFile(`[APPROVAL-CODE-EDIT] AcknowledgeCascadeCodeEdit(cascadeId=${sessionId.substring(0,8)}, accept=${approved}, stepIndices=[${effectiveStepIndex}])`);
|
||||
const ackResult = await sdk.ls.rawRPC('AcknowledgeCascadeCodeEdit', {
|
||||
cascadeId: sessionId,
|
||||
accept: true,
|
||||
accept: approved,
|
||||
stepIndices: [effectiveStepIndex],
|
||||
});
|
||||
logToFile(`[APPROVAL-PROTO-ACK] ✅ SUCCESS: ${JSON.stringify(ackResult).substring(0, 200)}`);
|
||||
return `RPC-PROTO-ACK:AcknowledgeCascadeCodeEdit`;
|
||||
logToFile(`[APPROVAL-CODE-EDIT] ✅ SUCCESS: ${JSON.stringify(ackResult).substring(0, 200)}`);
|
||||
return `RPC:AcknowledgeCascadeCodeEdit(accept=${approved})`;
|
||||
} catch (e: any) {
|
||||
logToFile(`[APPROVAL-PROTO-ACK] ❌ ${e.message.substring(0, 200)}`);
|
||||
// Fall through to HandleCascadeUserInteraction
|
||||
logToFile(`[APPROVAL-CODE-EDIT] ❌ ${e.message.substring(0, 200)}`);
|
||||
// Fallback: try HandleCascadeUserInteraction with runCommand
|
||||
logToFile(`[APPROVAL-CODE-EDIT] falling back to HandleCascadeUserInteraction`);
|
||||
interactionPayload = { runCommand: { confirm: true } };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user