From d691e2867534b947e3bd76eb14b614e71f785c9c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 16 Dec 2025 19:44:49 +0100 Subject: [PATCH] fix(gateway): cap chat.history to 1000 messages --- src/gateway/protocol/schema.ts | 2 +- src/gateway/server.test.ts | 47 ++++++++++++++++++++++++++++++++-- src/gateway/server.ts | 4 ++- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/gateway/protocol/schema.ts b/src/gateway/protocol/schema.ts index 9f3c52aeb..b2c5f8eeb 100644 --- a/src/gateway/protocol/schema.ts +++ b/src/gateway/protocol/schema.ts @@ -458,7 +458,7 @@ export const CronRunLogEntrySchema = Type.Object( export const ChatHistoryParamsSchema = Type.Object( { sessionKey: NonEmptyString, - limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 500 })), + limit: Type.Optional(Type.Integer({ minimum: 1 })), }, { additionalProperties: false }, ); diff --git a/src/gateway/server.test.ts b/src/gateway/server.test.ts index 3fa1f5d15..cbc1705bb 100644 --- a/src/gateway/server.test.ts +++ b/src/gateway/server.test.ts @@ -1786,8 +1786,8 @@ describe("gateway server", () => { ); expect(defaultRes.ok).toBe(true); const defaultMsgs = defaultRes.payload?.messages ?? []; - expect(defaultMsgs.length).toBe(200); - expect(firstContentText(defaultMsgs[0])).toBe("m100"); + expect(defaultMsgs.length).toBe(300); + expect(firstContentText(defaultMsgs[0])).toBe("m0"); const limitedRes = await rpcReq<{ messages?: unknown[] }>( ws, @@ -1802,6 +1802,49 @@ describe("gateway server", () => { expect(limitedMsgs.length).toBe(5); expect(firstContentText(limitedMsgs[0])).toBe("m295"); + const largeLines: string[] = []; + for (let i = 0; i < 1500; i += 1) { + largeLines.push( + JSON.stringify({ + message: { + role: "user", + content: [{ type: "text", text: `b${i}` }], + timestamp: Date.now() + i, + }, + }), + ); + } + await fs.writeFile( + path.join(dir, "sess-main.jsonl"), + largeLines.join("\n"), + "utf-8", + ); + + const cappedRes = await rpcReq<{ messages?: unknown[] }>( + ws, + "chat.history", + { + sessionKey: "main", + }, + ); + expect(cappedRes.ok).toBe(true); + const cappedMsgs = cappedRes.payload?.messages ?? []; + expect(cappedMsgs.length).toBe(1000); + expect(firstContentText(cappedMsgs[0])).toBe("b500"); + + const overLimitRes = await rpcReq<{ messages?: unknown[] }>( + ws, + "chat.history", + { + sessionKey: "main", + limit: 5000, + }, + ); + expect(overLimitRes.ok).toBe(true); + const overLimitMsgs = overLimitRes.payload?.messages ?? []; + expect(overLimitMsgs.length).toBe(1000); + expect(firstContentText(overLimitMsgs[0])).toBe("b500"); + ws.close(); await server.close(); }); diff --git a/src/gateway/server.ts b/src/gateway/server.ts index d0f81a7bd..28d2a8b50 100644 --- a/src/gateway/server.ts +++ b/src/gateway/server.ts @@ -1823,7 +1823,9 @@ export async function startGatewayServer( sessionId && storePath ? readSessionMessages(sessionId, storePath) : []; - const max = typeof limit === "number" ? limit : 200; + const hardMax = 1000; + const requested = typeof limit === "number" ? limit : hardMax; + const max = Math.min(hardMax, requested); const messages = rawMessages.length > max ? rawMessages.slice(-max) : rawMessages; const thinkingLevel =