79 lines
2.3 KiB
JavaScript
79 lines
2.3 KiB
JavaScript
function extensionName(config) {
|
|
return String(config?.name ?? '').trim();
|
|
}
|
|
|
|
async function readJson(response) {
|
|
const text = await response.text();
|
|
if (!response.ok) {
|
|
throw new Error(text || `upstream ${response.status}`);
|
|
}
|
|
return text ? JSON.parse(text) : null;
|
|
}
|
|
|
|
export function sessionStdioExtensionNames(extensions) {
|
|
return [
|
|
...new Set(
|
|
(extensions ?? [])
|
|
.filter((extension) => String(extension?.type ?? '').trim() === 'stdio')
|
|
.map(extensionName)
|
|
.filter(Boolean),
|
|
),
|
|
].sort();
|
|
}
|
|
|
|
export async function cancelSessionActiveRequest(apiFetch, sessionId, requestId) {
|
|
const normalizedSessionId = String(sessionId ?? '').trim();
|
|
const normalizedRequestId = String(requestId ?? '').trim();
|
|
if (!normalizedSessionId || !normalizedRequestId) {
|
|
return { cancelled: false, skipped: true };
|
|
}
|
|
|
|
const response = await apiFetch(
|
|
`/sessions/${encodeURIComponent(normalizedSessionId)}/cancel`,
|
|
{
|
|
method: 'POST',
|
|
body: JSON.stringify({ request_id: normalizedRequestId }),
|
|
},
|
|
);
|
|
const text = await response.text();
|
|
if (
|
|
!response.ok
|
|
&& ![404, 409, 410].includes(Number(response.status))
|
|
&& !/(?:not found|no active|already (?:finished|cancelled))/i.test(text)
|
|
) {
|
|
throw new Error(text || `upstream ${response.status}`);
|
|
}
|
|
return {
|
|
cancelled: response.ok,
|
|
skipped: !response.ok,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Stop per-session stdio MCP children while preserving the Goose conversation.
|
|
* Session reconciliation restores the required extensions before the next turn.
|
|
*/
|
|
export async function quiesceSessionStdioExtensions(apiFetch, sessionId) {
|
|
const normalizedSessionId = String(sessionId ?? '').trim();
|
|
if (!normalizedSessionId) return { removed: [], skipped: true };
|
|
|
|
const payload = await readJson(
|
|
await apiFetch(`/sessions/${encodeURIComponent(normalizedSessionId)}/extensions`),
|
|
);
|
|
const names = sessionStdioExtensionNames(payload?.extensions);
|
|
const removed = [];
|
|
for (const name of names) {
|
|
await readJson(
|
|
await apiFetch('/agent/remove_extension', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
session_id: normalizedSessionId,
|
|
name,
|
|
}),
|
|
}),
|
|
);
|
|
removed.push(name);
|
|
}
|
|
return { removed, skipped: names.length === 0 };
|
|
}
|