feat: auto-WAITING detection via stall + step query
This commit is contained in:
@@ -286,6 +286,9 @@ function setupMonitor() {
|
||||
let lastKnownStepCount = 0;
|
||||
let lastNotifyStepIndex = -1;
|
||||
let lastTaskStepIndex = -1;
|
||||
// WAITING detection
|
||||
let stalledPolls = 0;
|
||||
let lastPendingStepIndex = -1; // dedup: don't re-create pending for same step
|
||||
setInterval(async () => {
|
||||
pollCount++;
|
||||
try {
|
||||
@@ -317,16 +320,82 @@ function setupMonitor() {
|
||||
lastKnownStepCount = currentCount;
|
||||
lastNotifyStepIndex = bestSession.latestNotifyUserStep?.stepIndex ?? -1;
|
||||
lastTaskStepIndex = bestSession.latestTaskBoundaryStep?.stepIndex ?? -1;
|
||||
stalledPolls = 0;
|
||||
lastPendingStepIndex = -1;
|
||||
writeRegistration(activeSessionId);
|
||||
console.log(`Gravity Bridge: [POLL#${pollCount}] session: ${activeSessionId.substring(0, 8)} "${currentTitle}" steps=${currentCount} ${isRunning ? 'RUNNING' : 'idle'}`);
|
||||
return;
|
||||
}
|
||||
// No change?
|
||||
if (currentCount <= lastKnownStepCount && pollCount > 1) {
|
||||
if (pollCount % 30 === 0) {
|
||||
console.log(`Gravity Bridge: [POLL#${pollCount}] idle steps=${currentCount}`);
|
||||
// ── WAITING Detection ──
|
||||
// stepCount frozen + session still RUNNING = likely WAITING for user approval
|
||||
if (currentCount === lastKnownStepCount && isRunning) {
|
||||
stalledPolls++;
|
||||
if (stalledPolls >= 2) {
|
||||
// Query last steps to check for WAITING/PENDING
|
||||
try {
|
||||
const stepsResp = await sdk.ls.rawRPC('GetCascadeTrajectorySteps', { cascadeId: bestSessionId });
|
||||
const steps = stepsResp?.steps || [];
|
||||
if (steps.length > 0) {
|
||||
const lastStep = steps[steps.length - 1];
|
||||
const stepStatus = (lastStep.status || '').replace('CORTEX_STEP_STATUS_', '');
|
||||
const stepType = (lastStep.type || '').replace('CORTEX_STEP_TYPE_', '');
|
||||
const stepIdx = lastStep.metadata?.sourceTrajectoryStepInfo?.stepIndex ?? steps.length - 1;
|
||||
// Non-DONE step while session is RUNNING = user action needed
|
||||
if (stepStatus !== 'DONE' && stepStatus !== 'REJECTED' && stepIdx > lastPendingStepIndex) {
|
||||
// Extract command info from step
|
||||
let cmd = 'unknown';
|
||||
let desc = `${stepType} (${stepStatus})`;
|
||||
const toolName = lastStep.metadata?.toolCall?.name || '';
|
||||
if (lastStep.terminalCommand?.command) {
|
||||
cmd = lastStep.terminalCommand.command;
|
||||
desc = `Terminal: ${cmd}`;
|
||||
}
|
||||
else if (toolName === 'run_command') {
|
||||
// Extract from toolCall arguments
|
||||
try {
|
||||
const args = JSON.parse(lastStep.metadata.toolCall.argumentsJson || '{}');
|
||||
cmd = args.CommandLine || args.command || toolName;
|
||||
desc = `Command: ${cmd}`;
|
||||
}
|
||||
catch {
|
||||
cmd = toolName;
|
||||
}
|
||||
}
|
||||
else if (toolName) {
|
||||
cmd = toolName;
|
||||
desc = `Tool: ${toolName}`;
|
||||
}
|
||||
// Auto-create pending file
|
||||
const rid = Date.now().toString();
|
||||
const pending = {
|
||||
request_id: rid,
|
||||
conversation_id: bestSessionId,
|
||||
command: cmd.substring(0, 200),
|
||||
description: desc.substring(0, 200),
|
||||
timestamp: Date.now() / 1000,
|
||||
status: 'pending',
|
||||
project_name: projectName,
|
||||
step_index: stepIdx,
|
||||
step_type: stepType,
|
||||
step_status: stepStatus,
|
||||
auto_detected: true,
|
||||
};
|
||||
const pendingDir = path.join(bridgePath, 'pending');
|
||||
fs.writeFileSync(path.join(pendingDir, `${rid}.json`), JSON.stringify(pending, null, 2));
|
||||
lastPendingStepIndex = stepIdx;
|
||||
stalledPolls = 0; // reset stall counter after pending created
|
||||
logToFile(`[WAITING] detected step=${stepIdx} type=${stepType} status=${stepStatus} cmd=${cmd.substring(0, 60)}`);
|
||||
console.log(`Gravity Bridge: [POLL#${pollCount}] WAITING detected! step=${stepIdx} cmd=${cmd.substring(0, 40)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
logToFile(`[WAITING] step query failed: ${e.message}`);
|
||||
}
|
||||
}
|
||||
// Still process notify/task below (stepIndex may update without stepCount change)
|
||||
}
|
||||
else {
|
||||
stalledPolls = 0;
|
||||
}
|
||||
const delta = currentCount - lastKnownStepCount;
|
||||
lastKnownStepCount = currentCount;
|
||||
|
||||
Reference in New Issue
Block a user