fix(session): restore sandbox-fs after agent-run quiesce

Agent runs quiesced stdio MCP extensions including sandbox-fs, but reconcile
skipped re-adding missing stdio extensions and treated absent listings as OK.
Preserve sandbox-fs across quiesce and re-add other required stdio extensions
on the next reconcile so generate_image and write_file stay available.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-07 15:49:04 +08:00
parent 49ff7c9bad
commit d523b9595d
4 changed files with 96 additions and 20 deletions
+7 -1
View File
@@ -2,6 +2,9 @@ function extensionName(config) {
return String(config?.name ?? '').trim();
}
/** Stdio MCP extensions that must survive agent-run quiesce (page write + image gen). */
export const PRESERVED_STDIO_EXTENSIONS = new Set(['sandbox-fs']);
async function readJson(response) {
const text = await response.text();
if (!response.ok) {
@@ -52,6 +55,7 @@ export async function cancelSessionActiveRequest(apiFetch, sessionId, requestId)
/**
* Stop per-session stdio MCP children while preserving the Goose conversation.
* Session reconciliation restores the required extensions before the next turn.
* Critical page tools (sandbox-fs) stay attached so the next turn is not tool-less.
*/
export async function quiesceSessionStdioExtensions(apiFetch, sessionId) {
const normalizedSessionId = String(sessionId ?? '').trim();
@@ -60,7 +64,9 @@ export async function quiesceSessionStdioExtensions(apiFetch, sessionId) {
const payload = await readJson(
await apiFetch(`/sessions/${encodeURIComponent(normalizedSessionId)}/extensions`),
);
const names = sessionStdioExtensionNames(payload?.extensions);
const names = sessionStdioExtensionNames(payload?.extensions).filter(
(name) => !PRESERVED_STDIO_EXTENSIONS.has(name),
);
const removed = [];
for (const name of names) {
await readJson(