fix: diff review uses cumulative file tracking instead of IDLE-time step scan
This commit is contained in:
@@ -1457,6 +1457,7 @@ function setupMonitor() {
|
|||||||
let lastRelayedTaskText = ''; // dedup TASK_BOUNDARY relay
|
let lastRelayedTaskText = ''; // dedup TASK_BOUNDARY relay
|
||||||
let wasRunning = false; // track RUNNING→IDLE transition for response capture
|
let wasRunning = false; // track RUNNING→IDLE transition for response capture
|
||||||
let lastUserInputStepIdx = -1; // track user input for response matching
|
let lastUserInputStepIdx = -1; // track user input for response matching
|
||||||
|
let pendingModifiedFiles = []; // accumulate modified files during RUNNING
|
||||||
let lastResponseCaptureStep = -1; // dedup: don't capture same response twice
|
let lastResponseCaptureStep = -1; // dedup: don't capture same response twice
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
pollCount++;
|
pollCount++;
|
||||||
@@ -1546,6 +1547,21 @@ function setupMonitor() {
|
|||||||
const actualIdx = rtOffset + ri;
|
const actualIdx = rtOffset + ri;
|
||||||
if (actualIdx <= lastResponseCaptureStep)
|
if (actualIdx <= lastResponseCaptureStep)
|
||||||
continue;
|
continue;
|
||||||
|
// Track file write steps for diff review
|
||||||
|
if (s?.metadata?.toolCall?.argumentsJson) {
|
||||||
|
try {
|
||||||
|
const tcArgs = JSON.parse(s.metadata.toolCall.argumentsJson);
|
||||||
|
const tf = tcArgs.TargetFile || tcArgs.target_file || '';
|
||||||
|
if (tf) {
|
||||||
|
const bn = tf.split(/[\\/]/).pop() || tf;
|
||||||
|
if (!pendingModifiedFiles.includes(bn)) {
|
||||||
|
pendingModifiedFiles.push(bn);
|
||||||
|
logToFile(`[DIFF-TRACK] + ${bn} (step ${actualIdx})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
if (sType.includes('PLANNER_RESPONSE') && s?.status?.includes('DONE')) {
|
if (sType.includes('PLANNER_RESPONSE') && s?.status?.includes('DONE')) {
|
||||||
const pr = s?.plannerResponse;
|
const pr = s?.plannerResponse;
|
||||||
if (pr) {
|
if (pr) {
|
||||||
@@ -2009,45 +2025,15 @@ function setupMonitor() {
|
|||||||
logToFile(`[RESPONSE-CAPTURE] error: ${re.message.substring(0, 100)}`);
|
logToFile(`[RESPONSE-CAPTURE] error: ${re.message.substring(0, 100)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ── Diff review detection: if session just went IDLE and file writes happened ──
|
// ── Diff review detection: if session just went IDLE and files were modified ──
|
||||||
if (wasRunning && !isRunning && sdk) {
|
if (wasRunning && !isRunning && pendingModifiedFiles.length > 0) {
|
||||||
try {
|
const fileList = pendingModifiedFiles.slice(0, 5).join(', ');
|
||||||
const drOffset = Math.max(0, currentCount - 10);
|
logToFile(`[DIFF-REVIEW] IDLE with ${pendingModifiedFiles.length} modified files: ${fileList}`);
|
||||||
const drResp = await sdk.ls.rawRPC('GetCascadeTrajectorySteps', {
|
|
||||||
cascadeId: bestSessionId,
|
|
||||||
stepOffset: drOffset,
|
|
||||||
verbosity: 1,
|
|
||||||
});
|
|
||||||
if (drResp?.steps?.length > 0) {
|
|
||||||
const fileWriteSteps = drResp.steps.filter((s) => {
|
|
||||||
const t = s?.type || '';
|
|
||||||
return t.includes('WRITE_TO_FILE') || t.includes('REPLACE_FILE') || t.includes('MULTI_REPLACE');
|
|
||||||
});
|
|
||||||
if (fileWriteSteps.length > 0) {
|
|
||||||
// Extract modified file names
|
|
||||||
const modifiedFiles = [];
|
|
||||||
for (const fw of fileWriteSteps) {
|
|
||||||
try {
|
|
||||||
const args = JSON.parse(fw?.metadata?.toolCall?.argumentsJson || '{}');
|
|
||||||
const f = args.TargetFile || args.target_file || '';
|
|
||||||
if (f) {
|
|
||||||
const basename = f.split(/[\\/]/).pop() || f;
|
|
||||||
if (!modifiedFiles.includes(basename))
|
|
||||||
modifiedFiles.push(basename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
const fileList = modifiedFiles.length > 0
|
|
||||||
? modifiedFiles.slice(0, 5).join(', ')
|
|
||||||
: `${fileWriteSteps.length}개 파일`;
|
|
||||||
logToFile(`[DIFF-REVIEW] ${fileWriteSteps.length} file write steps detected, files: ${fileList}`);
|
|
||||||
writeChatSnapshot(`📝 **코드 리뷰 대기**\n\n수정된 파일: ${fileList}\n\nAG에서 Accept all / Reject all로 확인해주세요.`);
|
writeChatSnapshot(`📝 **코드 리뷰 대기**\n\n수정된 파일: ${fileList}\n\nAG에서 Accept all / Reject all로 확인해주세요.`);
|
||||||
// Create pending for Discord approval
|
|
||||||
writePendingApproval({
|
writePendingApproval({
|
||||||
conversation_id: activeSessionId,
|
conversation_id: activeSessionId,
|
||||||
command: `코드 리뷰: ${fileList}`,
|
command: `코드 리뷰: ${fileList}`,
|
||||||
description: `${fileWriteSteps.length}개 파일이 수정되었습니다`,
|
description: `${pendingModifiedFiles.length}개 파일이 수정되었습니다`,
|
||||||
step_type: 'diff_review',
|
step_type: 'diff_review',
|
||||||
step_index: currentCount,
|
step_index: currentCount,
|
||||||
source: 'diff_review_detect',
|
source: 'diff_review_detect',
|
||||||
@@ -2056,12 +2042,7 @@ function setupMonitor() {
|
|||||||
{ text: 'Reject all', index: 1 },
|
{ text: 'Reject all', index: 1 },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
pendingModifiedFiles = []; // reset after notification
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (dre) {
|
|
||||||
logToFile(`[DIFF-REVIEW] error: ${dre.message?.substring(0, 100)}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
wasRunning = isRunning;
|
wasRunning = isRunning;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1432,6 +1432,7 @@ function setupMonitor() {
|
|||||||
let lastRelayedTaskText = ''; // dedup TASK_BOUNDARY relay
|
let lastRelayedTaskText = ''; // dedup TASK_BOUNDARY relay
|
||||||
let wasRunning = false; // track RUNNING→IDLE transition for response capture
|
let wasRunning = false; // track RUNNING→IDLE transition for response capture
|
||||||
let lastUserInputStepIdx = -1; // track user input for response matching
|
let lastUserInputStepIdx = -1; // track user input for response matching
|
||||||
|
let pendingModifiedFiles: string[] = []; // accumulate modified files during RUNNING
|
||||||
let lastResponseCaptureStep = -1; // dedup: don't capture same response twice
|
let lastResponseCaptureStep = -1; // dedup: don't capture same response twice
|
||||||
|
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
@@ -1525,6 +1526,20 @@ function setupMonitor() {
|
|||||||
const sType = s?.type || '';
|
const sType = s?.type || '';
|
||||||
const actualIdx = rtOffset + ri;
|
const actualIdx = rtOffset + ri;
|
||||||
if (actualIdx <= lastResponseCaptureStep) continue;
|
if (actualIdx <= lastResponseCaptureStep) continue;
|
||||||
|
// Track file write steps for diff review
|
||||||
|
if (s?.metadata?.toolCall?.argumentsJson) {
|
||||||
|
try {
|
||||||
|
const tcArgs = JSON.parse(s.metadata.toolCall.argumentsJson);
|
||||||
|
const tf = tcArgs.TargetFile || tcArgs.target_file || '';
|
||||||
|
if (tf) {
|
||||||
|
const bn = tf.split(/[\\/]/).pop() || tf;
|
||||||
|
if (!pendingModifiedFiles.includes(bn)) {
|
||||||
|
pendingModifiedFiles.push(bn);
|
||||||
|
logToFile(`[DIFF-TRACK] + ${bn} (step ${actualIdx})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
if (sType.includes('PLANNER_RESPONSE') && s?.status?.includes('DONE')) {
|
if (sType.includes('PLANNER_RESPONSE') && s?.status?.includes('DONE')) {
|
||||||
const pr = s?.plannerResponse;
|
const pr = s?.plannerResponse;
|
||||||
if (pr) {
|
if (pr) {
|
||||||
@@ -1962,43 +1977,15 @@ function setupMonitor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Diff review detection: if session just went IDLE and file writes happened ──
|
// ── Diff review detection: if session just went IDLE and files were modified ──
|
||||||
if (wasRunning && !isRunning && sdk) {
|
if (wasRunning && !isRunning && pendingModifiedFiles.length > 0) {
|
||||||
try {
|
const fileList = pendingModifiedFiles.slice(0, 5).join(', ');
|
||||||
const drOffset = Math.max(0, currentCount - 10);
|
logToFile(`[DIFF-REVIEW] IDLE with ${pendingModifiedFiles.length} modified files: ${fileList}`);
|
||||||
const drResp = await sdk.ls.rawRPC('GetCascadeTrajectorySteps', {
|
|
||||||
cascadeId: bestSessionId,
|
|
||||||
stepOffset: drOffset,
|
|
||||||
verbosity: 1,
|
|
||||||
});
|
|
||||||
if (drResp?.steps?.length > 0) {
|
|
||||||
const fileWriteSteps = drResp.steps.filter((s: any) => {
|
|
||||||
const t = s?.type || '';
|
|
||||||
return t.includes('WRITE_TO_FILE') || t.includes('REPLACE_FILE') || t.includes('MULTI_REPLACE');
|
|
||||||
});
|
|
||||||
if (fileWriteSteps.length > 0) {
|
|
||||||
// Extract modified file names
|
|
||||||
const modifiedFiles: string[] = [];
|
|
||||||
for (const fw of fileWriteSteps) {
|
|
||||||
try {
|
|
||||||
const args = JSON.parse(fw?.metadata?.toolCall?.argumentsJson || '{}');
|
|
||||||
const f = args.TargetFile || args.target_file || '';
|
|
||||||
if (f) {
|
|
||||||
const basename = f.split(/[\\/]/).pop() || f;
|
|
||||||
if (!modifiedFiles.includes(basename)) modifiedFiles.push(basename);
|
|
||||||
}
|
|
||||||
} catch { }
|
|
||||||
}
|
|
||||||
const fileList = modifiedFiles.length > 0
|
|
||||||
? modifiedFiles.slice(0, 5).join(', ')
|
|
||||||
: `${fileWriteSteps.length}개 파일`;
|
|
||||||
logToFile(`[DIFF-REVIEW] ${fileWriteSteps.length} file write steps detected, files: ${fileList}`);
|
|
||||||
writeChatSnapshot(`📝 **코드 리뷰 대기**\n\n수정된 파일: ${fileList}\n\nAG에서 Accept all / Reject all로 확인해주세요.`);
|
writeChatSnapshot(`📝 **코드 리뷰 대기**\n\n수정된 파일: ${fileList}\n\nAG에서 Accept all / Reject all로 확인해주세요.`);
|
||||||
// Create pending for Discord approval
|
|
||||||
writePendingApproval({
|
writePendingApproval({
|
||||||
conversation_id: activeSessionId,
|
conversation_id: activeSessionId,
|
||||||
command: `코드 리뷰: ${fileList}`,
|
command: `코드 리뷰: ${fileList}`,
|
||||||
description: `${fileWriteSteps.length}개 파일이 수정되었습니다`,
|
description: `${pendingModifiedFiles.length}개 파일이 수정되었습니다`,
|
||||||
step_type: 'diff_review',
|
step_type: 'diff_review',
|
||||||
step_index: currentCount,
|
step_index: currentCount,
|
||||||
source: 'diff_review_detect',
|
source: 'diff_review_detect',
|
||||||
@@ -2007,11 +1994,7 @@ function setupMonitor() {
|
|||||||
{ text: 'Reject all', index: 1 },
|
{ text: 'Reject all', index: 1 },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
pendingModifiedFiles = []; // reset after notification
|
||||||
}
|
|
||||||
} catch (dre: any) {
|
|
||||||
logToFile(`[DIFF-REVIEW] error: ${dre.message?.substring(0, 100)}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
wasRunning = isRunning;
|
wasRunning = isRunning;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|||||||
Reference in New Issue
Block a user