mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
fix(agent-cli): httpRequest rejects when the connection drops mid-body (#615 merge-time fix)
The response listened for 'data' and 'end' only. A socket closed after the headers emits 'error' on the response and never 'end', so the promise never settled. A one-shot `codeman agent` just exits, but the long-lived `codeman mcp` left that tool call unanswered forever. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
71647e090d
commit
dedf56e24b
2 files changed
+14
No files matched your search
@@ -302,6 +302,9 @@ export const httpRequest: ApiRequest = (ctx, options) => {
|
||||
(res) => {
|
||||
const chunks: Buffer[] = [];
|
||||
res.on('data', (chunk: Buffer) => chunks.push(chunk));
|
||||
// A connection dropped mid-body emits 'error' and never 'end'; without this the
|
||||
// promise never settles (and a long-lived `codeman mcp` never answers the call).
|
||||
res.on('error', reject);
|
||||
res.on('end', () => {
|
||||
const text = Buffer.concat(chunks).toString('utf-8');
|
||||
let json: ApiEnvelope | undefined;
|
||||
|
||||
@@ -660,6 +660,13 @@ describe('httpRequest', () => {
|
||||
res.writeHead(401, { 'Content-Type': 'text/plain' }).end('Unauthorized');
|
||||
return;
|
||||
}
|
||||
if (req.url?.startsWith('/reset')) {
|
||||
// Headers and half a body, then the connection drops (a restart mid-answer).
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.write('{"success":true,"data":');
|
||||
setTimeout(() => req.socket.destroy(), 50);
|
||||
return;
|
||||
}
|
||||
res
|
||||
.writeHead(200, { 'Content-Type': 'application/json' })
|
||||
.end(JSON.stringify({ success: true, data: { echo: true } }));
|
||||
@@ -702,6 +709,10 @@ describe('httpRequest', () => {
|
||||
expect(last.headers.authorization).toBeUndefined();
|
||||
});
|
||||
|
||||
it('rejects, rather than hanging, when the connection drops mid-body', async () => {
|
||||
await expect(httpRequest(ctx({ apiUrl }), { method: 'GET', path: '/reset', timeoutMs: 5000 })).rejects.toThrow();
|
||||
});
|
||||
|
||||
it('keeps a plain-text body when the answer is not JSON', async () => {
|
||||
const res = await httpRequest(ctx({ apiUrl }), { method: 'GET', path: '/plain' });
|
||||
expect(res.status).toBe(401);
|
||||
|
||||
Reference in new issue
Block a user