fix(agent-run): tolerate goosed stdio MCP listing gaps during session reconcile.
Memind CI / Test, build, and release guards (push) Failing after 4s

Skip hot-adding stdio extensions goosed omits from /extensions, stabilize MCP
scope during session start, and wire chat intent routing into the agent-run worker.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-01 20:02:33 +08:00
parent 9d78927d1b
commit cdc265d7e0
6 changed files with 202 additions and 68 deletions
+27
View File
@@ -66,6 +66,16 @@ export function extensionsNeedingRefresh(currentExtensions, desiredExtensions) {
continue;
}
if (!extensionConfigsMatch(ext, wanted)) {
const currentExec = extensionExecutionConfig(ext);
const wantedExec = extensionExecutionConfig(wanted);
const stdioCmdArgsMatch = currentExec.type === 'stdio'
&& wantedExec.type === 'stdio'
&& currentExec.cmd === wantedExec.cmd
&& JSON.stringify(currentExec.args) === JSON.stringify(wantedExec.args);
if (stdioCmdArgsMatch) {
// goosed cannot hot-refresh stdio MCP env/tool grants after session start.
continue;
}
toRemove.push(name);
toAdd.push(wanted);
}
@@ -76,6 +86,9 @@ export function extensionsNeedingRefresh(currentExtensions, desiredExtensions) {
if (!name) continue;
const exists = current.some((ext) => extensionName(ext) === name);
if (!exists) {
// goosed may omit active stdio MCP extensions from the session listing
// even though /agent/start already loaded them; do not hot-add stdio.
if (String(config?.type ?? '') === 'stdio') continue;
toAdd.push(config);
}
}
@@ -83,6 +96,17 @@ export function extensionsNeedingRefresh(currentExtensions, desiredExtensions) {
return { toRemove, toAdd };
}
function stdioListingOmissionAllowed(currentExt, desiredConfig) {
if (String(desiredConfig?.type ?? '') !== 'stdio') return false;
if (!currentExt) return true;
const currentExec = extensionExecutionConfig(currentExt);
const desiredExec = extensionExecutionConfig(desiredConfig);
return currentExec.type === 'stdio'
&& desiredExec.type === 'stdio'
&& currentExec.cmd === desiredExec.cmd
&& JSON.stringify(currentExec.args) === JSON.stringify(desiredExec.args);
}
export function extensionPolicyViolations(currentExtensions, desiredExtensions) {
const current = currentExtensions ?? [];
const desired = desiredExtensions ?? [];
@@ -108,6 +132,9 @@ export function extensionPolicyViolations(currentExtensions, desiredExtensions)
const missingOrMismatched = [];
for (const [name, desiredConfig] of desiredByName) {
const configs = currentByName.get(name) ?? [];
if (stdioListingOmissionAllowed(configs[0] ?? null, desiredConfig)) {
continue;
}
if (
configs.length !== 1
|| !extensionConfigsMatch(configs[0], desiredConfig)