fix(extension): guitar_score step-probe UTF-8 loop + approval stepIndex guard (v0.5.11)

This commit is contained in:
Variet Worker
2026-03-28 09:15:11 +09:00
parent d5fdc41f35
commit 7bbd8749d7
4 changed files with 93 additions and 3 deletions

View File

@@ -601,7 +601,79 @@ function setupMonitor() {
}
}
} catch (e: any) {
ctx.logToFile(`[STEP-PROBE] error: ${e.message}`);
ctx.logToFile(`[STEP-PROBE] error: ${e.message?.substring(0, 150)}`);
// UTF-8 invalid data in a step causes a permanent 500 error on full fetch.
// Attempt stepOffset to skip that step and fetch only recent steps.
const isUtf8Error = e.message?.includes('invalid UTF-8') || e.message?.includes('proto:');
if (isUtf8Error && ctx.sdk) {
try {
const utf8Offset = Math.max(0, currentCount - 20);
ctx.logToFile(`[STEP-PROBE] UTF-8 fallback: retrying with stepOffset=${utf8Offset}`);
const offsetResp = await ctx.sdk.ls.rawRPC('GetCascadeTrajectorySteps', {
cascadeId: bestSessionId,
stepOffset: utf8Offset,
verbosity: 1,
});
if (offsetResp?.steps?.length > 0) {
const offsetSteps = offsetResp.steps;
ctx.logToFile(`[STEP-PROBE] UTF-8 offset=${utf8Offset} returned ${offsetSteps.length} steps`);
let foundWaitingInOffset = false;
for (let osi = offsetSteps.length - 1; osi >= 0; osi--) {
const oStep = offsetSteps[osi];
if (oStep?.status === 'CORTEX_STEP_STATUS_WAITING') {
foundWaitingInOffset = true;
const toolCall = oStep?.metadata?.toolCall;
const toolName = toolCall?.name || (oStep.type || '').replace('CORTEX_STEP_TYPE_', '').toLowerCase();
let command = toolName;
if (toolCall?.argumentsJson) {
try {
const args = JSON.parse(toolCall.argumentsJson);
if (args.CommandLine) command = `${toolName}: ${args.CommandLine.substring(0, 1500)}`;
else if (args.TargetFile) command = `${toolName}: ${args.TargetFile}`;
else {
const val = args.DirectoryPath || args.SearchPath || args.AbsolutePath || args.Url || args.Query || args.Prompt || Object.values(args).find((v: any) => typeof v === 'string' && v.length > 2);
command = val ? `${toolName}: ${String(val).substring(0, 500)}` : `${toolName}: ${Object.keys(args).join(', ')}`;
}
} catch { command = toolName; }
}
const actualIndex = utf8Offset + osi;
ctx.logToFile(`[STEP-PROBE] ★ WAITING (via UTF-8 offset)! step=${actualIndex} type=${oStep.type} cmd='${command}'`);
if (actualIndex !== ctx.lastPendingStepIndex) {
ctx.stallProbed = true;
if (actualIndex > ctx.lastPendingStepIndex) ctx.lastPendingStepIndex = actualIndex;
lastPendingTime = Date.now();
ctx.sawRunningAfterPending = false;
if (ctx.projectName !== 'default') {
writePendingApproval({
conversation_id: ctx.activeSessionId,
command,
description: `Step #${actualIndex} (${(oStep.type || '').replace('CORTEX_STEP_TYPE_', '')})`,
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'
: ['browser_subagent', 'open_browser_url'].includes(toolName) ? 'browser_subagent'
: toolName,
step_index: actualIndex,
source: 'step_probe_utf8_offset',
});
}
}
// NOTE: no break — process ALL parallel WAITING steps
}
}
if (!foundWaitingInOffset) {
ctx.logToFile(`[STEP-PROBE] UTF-8 offset: no WAITING found — stallProbed=true to prevent loop`);
ctx.stallProbed = true; // prevent retry loop; resets on delta>0
ctx.sessionStalled = false;
}
} else {
ctx.logToFile(`[STEP-PROBE] UTF-8 offset returned empty — stallProbed=true`);
ctx.stallProbed = true;
}
} catch (oe: any) {
ctx.logToFile(`[STEP-PROBE] UTF-8 offset also failed: ${oe.message?.substring(0, 100)}`);
ctx.stallProbed = true; // permanent error — block retry loop; resets on delta>0
}
}
}
}