cb3fb352be
Memind CI / Test, build, and release guards (push) Failing after 11m45s
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>
149 lines
4.6 KiB
JavaScript
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 });
|
|
}
|