Files
memind/session-runtime-lifecycle.mjs
T

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 };
}