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:
@@ -1746,6 +1746,8 @@ function setupMonitor() {
|
||||
let wasRunning = false; // track RUNNING→IDLE transition for response capture
|
||||
let lastUserInputStepIdx = -1; // track user input for response matching
|
||||
let pendingModifiedFiles = []; // accumulate modified files during RUNNING
|
||||
let pendingModifiedFilePaths = []; // full paths for diff review
|
||||
let pendingEditStepIndices = []; // step indices for AcknowledgeCascadeCodeEdit
|
||||
let lastResponseCaptureStep = -1; // dedup: don't capture same response twice
|
||||
setInterval(async () => {
|
||||
pollCount++;
|
||||
@@ -1885,6 +1887,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})`);
|
||||
}
|
||||
}
|
||||
@@ -2070,7 +2074,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',
|
||||
});
|
||||
@@ -2133,7 +2139,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',
|
||||
});
|
||||
@@ -2437,8 +2445,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),
|
||||
});
|
||||
pendingModifiedFiles = []; // reset after notification
|
||||
pendingModifiedFilePaths = [];
|
||||
pendingEditStepIndices = [];
|
||||
}
|
||||
wasRunning = isRunning;
|
||||
}
|
||||
@@ -2587,39 +2599,96 @@ async function processResponseFile(filePath) {
|
||||
// DOM observer: renderer handles clicking via pollResponse
|
||||
// Step probe/stall: try RPC → VS Code commands → log results
|
||||
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) {
|
||||
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 = [];
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
else {
|
||||
// No dirty docs — try command anyway
|
||||
await vscode.commands.executeCommand(cmd);
|
||||
logToFile(`[RESPONSE] diff_review: no dirty docs, command executed anyway`);
|
||||
catch (rpcErr) {
|
||||
logToFile(`[DIFF-REVIEW-RPC] ❌ ${rpcErr.message.substring(0, 200)}`);
|
||||
}
|
||||
}
|
||||
catch (cmdErr) {
|
||||
logToFile(`[RESPONSE] diff_review command error: ${cmdErr.message}`);
|
||||
// ── 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 = [];
|
||||
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) {
|
||||
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) {
|
||||
logToFile(`[DIFF-REVIEW-CMD] error: ${cmdErr.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isDomObserver) {
|
||||
@@ -2949,21 +3018,23 @@ async function tryApprovalStrategies(approved, sessionId, stepType = '', stepInd
|
||||
// Build interaction sub-message based on step_type
|
||||
const typeLower = stepType.toLowerCase().replace('cortex_step_type_', '');
|
||||
let interactionPayload = {};
|
||||
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) {
|
||||
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 } };
|
||||
}
|
||||
}
|
||||
// Map step_type to interaction sub-message field
|
||||
|
||||
Reference in New Issue
Block a user