Files
memind/cursor-page-timeout-takeover.mjs
T
john cb3fb352be
Memind CI / Test, build, and release guards (push) Failing after 11m45s
feat(agent-run): retry goose page timeouts with Cursor executor
When a page-generation run times out without recoverable HTML, retry once
via Cursor code executor if MEMIND_CURSOR_PAGE_TIMEOUT_TAKEOVER is enabled.
Also release delivery contracts after successful deliverable recovery.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-11 13:40:05 +08:00

149 lines
4.6 KiB
JavaScript

import {
isGenericPageGenerationRequest,
isPageGenerationIntent,
} from './chat-skills.mjs';
import {
cursorExecutorEnabled,
resolvePreferredCodeExecutor,
} from './cursor-agent-launch.mjs';
import { enforcePageGenerationCursorRuntime } from './cursor-page-routing.mjs';
function envFlag(value, fallback = false) {
const raw = String(value ?? '').trim().toLowerCase();
if (!raw) return fallback;
return ['1', 'true', 'yes', 'on'].includes(raw);
}
export function cursorPageTimeoutTakeoverEnabled(env = process.env) {
return envFlag(env.MEMIND_CURSOR_PAGE_TIMEOUT_TAKEOVER, false);
}
function extractRunDisplayText(row) {
const message = row?.user_message_json;
const parsed = typeof message === 'string'
? (() => {
try {
return JSON.parse(message);
} catch {
return {};
}
})()
: (message ?? {});
const displayText = String(parsed?.metadata?.displayText ?? '').trim();
if (displayText) return displayText;
const content = parsed?.content;
if (typeof content === 'string') return content.trim();
if (Array.isArray(content)) {
return content
.filter((item) => item?.type === 'text')
.map((item) => String(item.text ?? '').trim())
.filter(Boolean)
.join('\n')
.trim();
}
return '';
}
function getRunOptionsFromMessage(userMessage) {
const metadata = userMessage?.metadata;
const runMetadata = metadata?.memindRun ?? metadata?.agentRun ?? {};
return {
toolMode: String(runMetadata?.toolMode ?? metadata?.toolMode ?? 'chat').trim().toLowerCase(),
taskType: runMetadata?.taskType ?? metadata?.taskType ?? null,
forceDeepReasoning: runMetadata?.forceDeepReasoning === true || metadata?.forceDeepReasoning === true,
};
}
function cursorExecutorAvailable(toolGatewayStatus, env = process.env) {
if (!cursorExecutorEnabled(env)) return false;
if (resolvePreferredCodeExecutor(env) !== 'cursor') return false;
if (!toolGatewayStatus?.enabled) return false;
const executors = Array.isArray(toolGatewayStatus.executors)
? toolGatewayStatus.executors.map((item) => String(item).trim().toLowerCase())
: [];
return executors.includes('cursor');
}
export function shouldRetryPageGenerationWithCursor({
row,
error = null,
toolGatewayStatus = null,
env = process.env,
} = {}) {
if (!cursorPageTimeoutTakeoverEnabled(env)) return false;
if (String(error?.code ?? '') !== 'AGENT_RUN_TIMEOUT') return false;
if (!cursorExecutorAvailable(toolGatewayStatus, env)) return false;
const userMessage = typeof row?.user_message_json === 'string'
? (() => {
try {
return JSON.parse(row.user_message_json);
} catch {
return {};
}
})()
: (row?.user_message_json ?? {});
const runMetadata = userMessage?.metadata?.memindRun ?? userMessage?.metadata?.agentRun ?? {};
if (runMetadata.pageCursorDefault === true || runMetadata.cursorTimeoutTakeover === true) {
return false;
}
if (String(runMetadata.requiredExecutor ?? runMetadata.executor ?? '').trim().toLowerCase() === 'cursor') {
return false;
}
const taskText = extractRunDisplayText(row);
if (!isPageGenerationIntent(taskText) || isGenericPageGenerationRequest(taskText)) {
return false;
}
return true;
}
export function buildCursorPageTimeoutTakeover(row, { env = process.env } = {}) {
const userMessage = typeof row?.user_message_json === 'string'
? (() => {
try {
return JSON.parse(row.user_message_json);
} catch {
return {};
}
})()
: (row?.user_message_json ?? {});
const runOptions = getRunOptionsFromMessage(userMessage);
const enforced = enforcePageGenerationCursorRuntime(userMessage, {
rawToolMode: runOptions.toolMode,
taskType: runOptions.taskType,
forceDeepReasoning: runOptions.forceDeepReasoning ?? true,
env,
channelEligible: true,
policy: null,
});
if (!enforced.requiredExecutor) return null;
const metadata = enforced.userMessage?.metadata ?? {};
const memindRun = metadata.memindRun ?? {};
const updatedMessage = {
...enforced.userMessage,
metadata: {
...metadata,
memindRun: {
...memindRun,
cursorTimeoutTakeover: true,
},
},
};
return {
userMessage: updatedMessage,
runOptions: {
toolMode: enforced.rawToolMode,
taskType: enforced.taskType,
forceDeepReasoning: enforced.forceDeepReasoning,
requiredExecutor: enforced.requiredExecutor,
},
};
}
export function resolveCursorPageTimeoutTakeover(input) {
if (!shouldRetryPageGenerationWithCursor(input)) return null;
return buildCursorPageTimeoutTakeover(input.row, { env: input.env });
}