fix(extension): diff_review use agentAcceptAllInFile instead of dead RPC strategies (v0.3.15)

This commit is contained in:
Variet Worker
2026-03-16 18:43:04 +09:00
parent 5a1d4f0b0c
commit 0fdf668abc
4 changed files with 140 additions and 211 deletions

View File

@@ -2595,120 +2595,84 @@ async function processResponseFile(filePath: string) {
let diffReviewDone = false;
const targetSession = sessionId || activeSessionId;
let modifiedFiles: string[] = []; // shared between Strategy 1 and 2
let modifiedFiles: string[] = [];
// ── Strategy 1: acknowledgeCodeActionStep RPC (correct AG LS method) ──
// Discovered via AG source reverse-engineering: the internal LS method is
// `acknowledgeCodeActionStep` (proto ID 167), NOT `AcknowledgeCascadeCodeEdit`.
// Accept all button → fireEvent({type:"accept-all-in-file"}) → submitCodeAcknowledgement → acknowledgeCodeActionStep
if (sdk) {
// Load tracked step indices and modified files from memory cache or pending file
const trackedSteps: number[] = [];
const memMeta = diffReviewMetadata.get(resp.request_id);
if (memMeta) {
trackedSteps.push(...memMeta.edit_step_indices);
modifiedFiles = memMeta.modified_files;
diffReviewMetadata.delete(resp.request_id);
logToFile(`[DIFF-REVIEW] loaded from memory: steps=[${trackedSteps.join(',')}] files=${modifiedFiles.length}`);
} else {
try {
// Get tracked step indices from in-memory cache FIRST (pending file may be deleted by Collector)
const trackedSteps: number[] = [];
const memMeta = diffReviewMetadata.get(resp.request_id);
if (memMeta) {
trackedSteps.push(...memMeta.edit_step_indices);
modifiedFiles = memMeta.modified_files;
diffReviewMetadata.delete(resp.request_id); // cleanup
logToFile(`[DIFF-REVIEW-RPC] loaded from memory: steps=[${trackedSteps.join(',')}] files=${modifiedFiles.length}`);
} else {
// Fallback: try pending file (may already be deleted)
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);
if (pd.modified_files) modifiedFiles = pd.modified_files;
}
} catch { }
}
// If no tracked steps, use the step_index from the pending
if (trackedSteps.length === 0 && pendingStepIndex > 0) {
trackedSteps.push(pendingStepIndex);
const pf = path.join(bridgePath, 'pending', `${resp.request_id}.json`);
if (fs.existsSync(pf)) {
const pd = JSON.parse(fs.readFileSync(pf, 'utf-8'));
if (pd.edit_step_indices) trackedSteps.push(...pd.edit_step_indices);
if (pd.modified_files) modifiedFiles = pd.modified_files;
}
} catch { }
}
if (trackedSteps.length === 0 && pendingStepIndex > 0) {
trackedSteps.push(pendingStepIndex);
}
logToFile(`[DIFF-REVIEW-RPC] acknowledgeCodeActionStep(session=${targetSession.substring(0, 8)}, accept=${isAccept}, steps=[${trackedSteps.join(',')}])`);
// Strategy 1a: VS Code command (most reliable — same path as UI button)
try {
await vscode.commands.executeCommand('antigravity.prioritized.submitCodeAcknowledgement');
logToFile(`[DIFF-REVIEW-RPC] ✅ submitCodeAcknowledgement command OK`);
diffReviewDone = true;
} catch (cmdErr: any) {
logToFile(`[DIFF-REVIEW-RPC] submitCodeAcknowledgement command error: ${cmdErr.message?.substring(0, 200)}`);
}
// ── Strategy 1: VS Code command (confirmed registered at runtime) ──
// agentAcceptAllInFile / agentRejectAllInFile are the ONLY working diff_review
// commands. RPC methods (acknowledgeCodeActionStep → 404, AcknowledgeCascadeCodeEdit
// → no-op {}, submitCodeAcknowledgement → not registered) are all dead ends.
// The command requires the diff review file to be focused in the editor.
try {
// First, open the Review Changes panel to ensure diff UI is active
try {
await vscode.commands.executeCommand('antigravity.openReviewChanges');
logToFile(`[DIFF-REVIEW] openReviewChanges OK`);
await new Promise(r => setTimeout(r, 500));
} catch { }
// Strategy 1b: Direct LS RPC with correct method name
if (!diffReviewDone) {
if (modifiedFiles.length > 0) {
// Focus each modified file and execute accept/reject
for (const fp of modifiedFiles) {
try {
const ackResult = await sdk.ls.rawRPC('acknowledgeCodeActionStep', {
cascadeId: targetSession,
accept: isAccept,
...(trackedSteps.length > 0 ? { stepIndices: trackedSteps } : {}),
});
logToFile(`[DIFF-REVIEW-RPC] ✅ acknowledgeCodeActionStep: ${JSON.stringify(ackResult).substring(0, 300)}`);
const uri = vscode.Uri.file(fp);
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} on ${fp.split(/[\\/]/).pop()} OK`);
diffReviewDone = true;
} catch (rpcErr1: any) {
logToFile(`[DIFF-REVIEW-RPC] acknowledgeCodeActionStep error: ${rpcErr1.message?.substring(0, 200)}`);
} catch (e: any) {
logToFile(`[DIFF-REVIEW] per-file error on ${fp}: ${e.message?.substring(0, 80)}`);
}
}
} else {
// No file list — just execute command (best effort on currently focused file)
await vscode.commands.executeCommand(cmd);
logToFile(`[DIFF-REVIEW] ✅ ${cmd} executed (no file list)`);
diffReviewDone = true;
}
} catch (cmdErr: any) {
logToFile(`[DIFF-REVIEW] Strategy 1 command error: ${cmdErr.message?.substring(0, 200)}`);
}
// Strategy 1c: Legacy method name (fallback)
if (!diffReviewDone) {
try {
const ackLegacy = await sdk.ls.rawRPC('AcknowledgeCascadeCodeEdit', {
cascadeId: targetSession,
accept: isAccept,
...(trackedSteps.length > 0 ? { stepIndices: trackedSteps } : {}),
});
logToFile(`[DIFF-REVIEW-RPC] ✅ AcknowledgeCascadeCodeEdit (legacy): ${JSON.stringify(ackLegacy).substring(0, 300)}`);
diffReviewDone = true;
} catch (rpcErr2: any) {
logToFile(`[DIFF-REVIEW-RPC] AcknowledgeCascadeCodeEdit (legacy) error: ${rpcErr2.message?.substring(0, 200)}`);
}
}
} catch (outerErr: any) {
logToFile(`[DIFF-REVIEW-RPC] ❌ outer error: ${outerErr.message?.substring(0, 200)}`);
// ── Strategy 2: Try individual hunk accept/reject as fallback ──
if (!diffReviewDone) {
try {
const hunkCmd = isAccept
? 'antigravity.prioritized.agentAcceptFocusedHunk'
: 'antigravity.prioritized.agentRejectFocusedHunk';
await vscode.commands.executeCommand(hunkCmd);
logToFile(`[DIFF-REVIEW] ✅ ${hunkCmd} fallback OK`);
diffReviewDone = true;
} catch (hunkErr: any) {
logToFile(`[DIFF-REVIEW] hunk fallback error: ${hunkErr.message?.substring(0, 100)}`);
}
}
// ── 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: Use modifiedFiles from Strategy 1 (already loaded from memory/file above)
// 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}`);
}
logToFile(`[DIFF-REVIEW] ❌ ALL strategies failed for rid=${resp.request_id}`);
}
} else if (isDomObserver) {
// DOM observer path: ALSO try RPC strategies (renderer click is unreliable)