Compare commits
2 Commits
5a1d4f0b0c
...
0035394b9c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0035394b9c | ||
|
|
0fdf668abc |
@@ -571,16 +571,24 @@
|
||||
|
||||
### [2026-03-16] AcknowledgeCascadeCodeEdit SUCCESS → diff review bar 미해제 — **잘못된 RPC 메서드명**
|
||||
- **증상**: `AcknowledgeCascadeCodeEdit(session=xxx, accept=true, steps=[40])` → `SUCCESS: {}` 반환 → AG diff review bar 여전히 표시됨
|
||||
- **원인**: **RPC 메서드명 자체가 틀렸음.** AG 내부 LS 메서드는 `AcknowledgeCascadeCodeEdit`가 아닌 **`acknowledgeCodeActionStep`**(proto ID 167). AG 소스 역분석으로 확인 — `jetskiAgent/main.js`에서 `acknowledgeCodeActionStep:async K=>{e&&await e.acknowledgeCodeActionStep(ur(vKa,K))}` 발견. Accept all 버튼 클릭 체인: `fireEvent({type:"accept-all-in-file"})` → `submitCodeAcknowledgement` 커맨드 → `acknowledgeCodeActionStep` LS RPC. `AcknowledgeCascadeCodeEdit`는 proto unknown field 무시로 `{}` 반환 (에러도 아닌 no-op)
|
||||
- **해결**: v0.3.14에서 3단계 전략으로 변경: (1) `submitCodeAcknowledgement` VS Code 커맨드 (AG UI와 동일 경로), (2) `acknowledgeCodeActionStep` rawRPC, (3) `AcknowledgeCascadeCodeEdit` 레거시 폴백
|
||||
- **주의**: AG의 RPC는 잘못된 메서드명도 에러 없이 `{}` 반환함. proto unknown field 동작으로 인해 디버깅이 매우 어려움. **반드시 AG 소스(`jetskiAgent/main.js`, `workbench.desktop.main.js`)에서 실제 메서드명을 확인** 후 사용할 것
|
||||
- **원인**: **RPC 메서드명 자체가 틀렸음.** AG 내부 LS 메서드는 `AcknowledgeCascadeCodeEdit`가 아닌 **`acknowledgeCodeActionStep`**(proto ID 167). AG 소스 역분석으로 확인. 그러나 `acknowledgeCodeActionStep`도 ConnectRPC 404 반환 (LS의 `exa.language_server_pb.LanguageServerService`에 미등록). `submitCodeAcknowledgement` VS Code 커맨드도 런타임 미등록
|
||||
- **해결**: ~~v0.3.14 3단계 RPC 전략~~ 모두 실패. **v0.3.15**: `agentAcceptAllInFile` / `agentRejectAllInFile` VS Code 커맨드 사용 (런타임에 등록 확인됨). `openReviewChanges` → 파일별 포커스 → 커맨드 실행
|
||||
- **주의**: AG의 RPC는 잘못된 메서드명도 에러 없이 `{}` 반환함 (proto unknown field). `AcknowledgeCascadeCodeEdit`가 `{}` 반환 → `diffReviewDone=true` 설정 → 실제 동작하는 전략 차단이 핵심 버그였음. **RPC `{}`는 실패로 간주해야 함**
|
||||
|
||||
### [2026-03-16] diff_review RPC 3개 전략 모두 dead-end — VS Code 커맨드만 유효
|
||||
- **증상**: v0.3.14 E2E 테스트에서 3개 RPC 전략 모두 실패, diff review bar 해제 안 됨
|
||||
- **원인**: (1) `submitCodeAcknowledgement`: AG 런타임 119개 명령에 미등록, (2) `acknowledgeCodeActionStep`: ConnectRPC 404 (LS 서비스에 미등록), (3) `AcknowledgeCascadeCodeEdit`: `{}` no-op 반환 후 `diffReviewDone=true` → Strategy 2 차단
|
||||
- **해결**: v0.3.15에서 dead-end RPC 3개 제거. `agentAcceptAllInFile` / `agentRejectAllInFile` (런타임 등록 확인) + `openReviewChanges` + 파일별 포커스 방식으로 전환. Hunk 단위 fallback 추가 (`agentAcceptFocusedHunk`)
|
||||
- **주의**: diff_review Accept/Reject를 RPC로 해결하려는 시도 **모두 실패 확정**. VS Code 커맨드 기반만 유효. 단, 이 커맨드도 diff editor 포커스 의존성 있을 수 있음 — 재시작 후 E2E 검증 필요
|
||||
|
||||
### [2026-03-16] AG 소스 역분석 — diff review 내부 동작 체인
|
||||
- **증상**: Accept all / Reject all 버튼의 내부 동작을 Extension에서 프로그래밍 방식으로 재현해야 함
|
||||
- **원인**: AG 공식 API/문서 없음. VS Code 커맨드 중 많은 것이 미등록 상태
|
||||
- **해결**: AG 설치 경로의 JS 소스에서 직접 역분석. 핵심 발견:
|
||||
- **LS 메서드**: `acknowledgeCodeActionStep` (proto ID 167, 메시지 타입 `vKa`/`QLc`)
|
||||
- **VS Code 커맨드**: `antigravity.prioritized.submitCodeAcknowledgement` (SUBMIT_CODE_ACKNOWLEDGEMENT)
|
||||
- **Accept all 체인**: UI 클릭 → `fireEvent({type:"accept-all-in-file", uri: currentFile})` → `submitCodeAcknowledgement` → `acknowledgeCodeActionStep`
|
||||
- **LS 메서드**: `acknowledgeCodeActionStep` (proto ID 167, 메시지 타입 `vKa`/`QLc`) — 단, ConnectRPC 404
|
||||
- **VS Code 커맨드**: `antigravity.prioritized.submitCodeAcknowledgement` — 미등록
|
||||
- **실제 동작 커맨드**: `antigravity.prioritized.agentAcceptAllInFile` / `agentRejectAllInFile` (런타임 등록 확인)
|
||||
- **Accept all 체인**: UI 클릭 → `fireEvent({type:"accept-all-in-file"})` → 내부 처리
|
||||
- **파일 위치**: `%LOCALAPPDATA%\Programs\Antigravity\resources\app\out\jetskiAgent\main.js` (LS 메서드 정의), `vs\workbench\workbench.desktop.main.js` (UI 커맨드 + 핸들러)
|
||||
- **주의**: Python `re.finditer`로 대용량 JS 검색 시 PowerShell `IndexOf`보다 안정적. minified JS에서 변수명(`vKa`, `QLc` 등)은 버전마다 변경됨
|
||||
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
|---|------|------|------|------|
|
||||
| 001 | 07:30~11:10 | 승인 상태 관리 근본 원인 분석 + v0.3.12 수정 (sawRunningAfterPending gate) + approval-flow.md 시스템 Flow 문서 + known-issues 2건 추가 | `2d9fe96` | ✅ |
|
||||
| 002 | 13:25~14:20 | diff_review 핸들러 2-strategy 리팩토링 + 배포 불일치 발견/수정 + pending 순서 8초 지연 + 1차 테스트 (버튼 OK, RPC 미배포→재배포) + known-issues 2건 | `f302984` | ✅ |
|
||||
| 003 | 15:18~16:55 | diff_review steps=[] 근본 원인 분석 + 인메모리 캐시 (v0.3.13) + 3차 E2E (RPC SUCCESS but no-op) + 4가지 파라미터 실험 배포 | `00b9491` | 🔧 |
|
||||
| 004 | 17:05~18:00 | AG 소스 역분석 — `AcknowledgeCascadeCodeEdit`→`acknowledgeCodeActionStep` 메서드명 오류 발견 + v0.3.14 3단계 전략 배포 + known-issues 2건 업데이트 | `08c2c86` | 🔧 |
|
||||
| 003 | 15:18~16:55 | diff_review steps=[] 근본 원인 분석 + 인메모리 캐시 (v0.3.13) + 3차 E2E (RPC SUCCESS but no-op) + 4가지 파라미터 실험 배포 | `00b9491` | ✅ |
|
||||
| 004 | 17:05~18:00 | AG 소스 역분석 — `AcknowledgeCascadeCodeEdit`→`acknowledgeCodeActionStep` 메서드명 오류 발견 + v0.3.14 3단계 전략 배포 + known-issues 2건 업데이트 | `5a1d4f0` | ✅ |
|
||||
| 005 | 18:13~18:43 | v0.3.14 E2E 테스트 → RPC 3개 전략 모두 실패 확인 + v0.3.15 agentAcceptAllInFile 전환 배포 + known-issues 업데이트 | `0fdf668` | 🔧 |
|
||||
|
||||
@@ -2625,123 +2625,88 @@ async function processResponseFile(filePath) {
|
||||
logToFile(`[RESPONSE] diff_review → ${isAccept ? 'ACCEPT' : 'REJECT'} (btnIdx=${btnIdx})`);
|
||||
let diffReviewDone = false;
|
||||
const targetSession = sessionId || activeSessionId;
|
||||
let modifiedFiles = []; // shared between Strategy 1 and 2
|
||||
// ── 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) {
|
||||
try {
|
||||
// Get tracked step indices from in-memory cache FIRST (pending file may be deleted by Collector)
|
||||
const trackedSteps = [];
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
logToFile(`[DIFF-REVIEW-RPC] submitCodeAcknowledgement command error: ${cmdErr.message?.substring(0, 200)}`);
|
||||
}
|
||||
// Strategy 1b: Direct LS RPC with correct method name
|
||||
if (!diffReviewDone) {
|
||||
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)}`);
|
||||
diffReviewDone = true;
|
||||
}
|
||||
catch (rpcErr1) {
|
||||
logToFile(`[DIFF-REVIEW-RPC] acknowledgeCodeActionStep error: ${rpcErr1.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) {
|
||||
logToFile(`[DIFF-REVIEW-RPC] AcknowledgeCascadeCodeEdit (legacy) error: ${rpcErr2.message?.substring(0, 200)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (outerErr) {
|
||||
logToFile(`[DIFF-REVIEW-RPC] ❌ outer error: ${outerErr.message?.substring(0, 200)}`);
|
||||
}
|
||||
let modifiedFiles = [];
|
||||
// Load tracked step indices and modified files from memory cache or pending file
|
||||
const trackedSteps = [];
|
||||
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}`);
|
||||
}
|
||||
// ── Strategy 2: Open review panel + focus file + VS Code command ──
|
||||
if (!diffReviewDone) {
|
||||
else {
|
||||
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));
|
||||
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 { }
|
||||
// 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) {
|
||||
logToFile(`[DIFF-REVIEW-CMD] per-file error on ${filePath}: ${e.message?.substring(0, 80)}`);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (trackedSteps.length === 0 && pendingStepIndex > 0) {
|
||||
trackedSteps.push(pendingStepIndex);
|
||||
}
|
||||
// ── 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 { }
|
||||
if (modifiedFiles.length > 0) {
|
||||
// Focus each modified file and execute accept/reject
|
||||
for (const fp of modifiedFiles) {
|
||||
try {
|
||||
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 (e) {
|
||||
logToFile(`[DIFF-REVIEW] per-file error on ${fp}: ${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)`);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
logToFile(`[DIFF-REVIEW-CMD] error: ${cmdErr.message}`);
|
||||
}
|
||||
catch (cmdErr) {
|
||||
logToFile(`[DIFF-REVIEW] Strategy 1 command error: ${cmdErr.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) {
|
||||
logToFile(`[DIFF-REVIEW] hunk fallback error: ${hunkErr.message?.substring(0, 100)}`);
|
||||
}
|
||||
}
|
||||
if (!diffReviewDone) {
|
||||
logToFile(`[DIFF-REVIEW] ❌ ALL strategies failed for rid=${resp.request_id}`);
|
||||
}
|
||||
}
|
||||
else if (isDomObserver) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
||||
"name": "gravity-bridge",
|
||||
"displayName": "Gravity Bridge",
|
||||
"description": "Antigravity ↔ Discord 브리지 연동 확장",
|
||||
"version": "0.3.14",
|
||||
"version": "0.3.15",
|
||||
"publisher": "variet",
|
||||
"engines": {
|
||||
"vscode": "^1.100.0"
|
||||
|
||||
@@ -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');
|
||||
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);
|
||||
}
|
||||
|
||||
// ── 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 { }
|
||||
|
||||
if (modifiedFiles.length > 0) {
|
||||
// Focus each modified file and execute accept/reject
|
||||
for (const fp of modifiedFiles) {
|
||||
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);
|
||||
}
|
||||
|
||||
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 1b: Direct LS RPC with correct method name
|
||||
if (!diffReviewDone) {
|
||||
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)
|
||||
|
||||
10
test_diff_review.py
Normal file
10
test_diff_review.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# Test file for diff_review E2E verification
|
||||
# Created: 2026-03-16 18:21
|
||||
# Purpose: Trigger AG diff review bar to test remote Accept/Reject from Discord
|
||||
|
||||
def test_function():
|
||||
"""This function exists solely to trigger a diff review."""
|
||||
return "diff_review_test_v0.3.14"
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(test_function())
|
||||
Reference in New Issue
Block a user