Merge branch 'main' into memory_usage3

This commit is contained in:
Spencer
2026-04-09 18:10:24 -04:00
committed by GitHub
19 changed files with 987 additions and 695 deletions
@@ -305,6 +305,28 @@ describe('oauth-flow', () => {
'Invalid value for OAUTH_CALLBACK_PORT',
);
});
it('should settle on timeout without keeping the process alive', async () => {
vi.useFakeTimers();
try {
const server = startCallbackServer('timeout-state');
await server.port;
const responsePromise = server.response.catch((e: Error) => {
if (e.message !== 'OAuth callback timeout') throw e;
return e;
});
// Advance timers by 5 minutes to trigger the timeout
await vi.advanceTimersByTimeAsync(5 * 60 * 1000);
const error = await responsePromise;
expect(error).toBeInstanceOf(Error);
expect((error as Error).message).toBe('OAuth callback timeout');
} finally {
vi.useRealTimers();
}
});
});
describe('exchangeCodeForToken', () => {
+20 -5
View File
@@ -116,6 +116,8 @@ export function startCallbackServer(
portReject = reject;
});
let timeoutId: NodeJS.Timeout | undefined;
const responsePromise = new Promise<OAuthAuthorizationResponse>(
(resolve, reject) => {
let serverPort: number;
@@ -221,18 +223,31 @@ export function startCallbackServer(
portResolve(serverPort); // Resolve port promise immediately
});
// Timeout after 5 minutes
setTimeout(
const abortController = new AbortController();
timeoutId = setTimeout(
() => {
server.close();
reject(new Error('OAuth callback timeout'));
abortController.abort(new Error('OAuth callback timeout'));
},
5 * 60 * 1000,
);
timeoutId.unref();
const onAbort = () => {
server.close();
reject(abortController.signal.reason);
};
abortController.signal.addEventListener('abort', onAbort, { once: true });
server.on('close', () => {
abortController.signal.removeEventListener('abort', onAbort);
});
},
);
return { port: portPromise, response: responsePromise };
return {
port: portPromise,
response: responsePromise,
};
}
/**
+5 -2
View File
@@ -98,8 +98,11 @@ export async function deleteSubagentSessionDirAndArtifactsAsync(
});
for (const file of files) {
if (file.isFile() && file.name.endsWith('.json')) {
const agentId = path.basename(file.name, '.json');
if (
file.isFile() &&
(file.name.endsWith('.json') || file.name.endsWith('.jsonl'))
) {
const agentId = path.basename(file.name, path.extname(file.name));
await deleteSessionArtifactsAsync(agentId, tempDir);
}
}