mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
fix(sessions): history pagination skips projected messages or stops advancing (#129099)
* fix(sessions): preserve history pagination replay and progress * fix(sessions): avoid shadowing history cursor sequence
This commit is contained in:
committed by
GitHub
parent
cb7a1a76df
commit
75c01c0611
@@ -481,6 +481,55 @@ describe("sessions_history redaction", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves the Gateway replay cursor for projected siblings from the same row", async () => {
|
||||
const tool = createSessionsHistoryTool({
|
||||
config: {},
|
||||
callGateway: async <T = Record<string, unknown>>(): Promise<T> =>
|
||||
({
|
||||
messages: [
|
||||
{ role: "assistant", content: "projected sibling", __openclaw: { seq: 8 } },
|
||||
{ role: "assistant", content: "latest", __openclaw: { seq: 9 } },
|
||||
],
|
||||
offset: 0,
|
||||
nextOffset: 2,
|
||||
hasMore: true,
|
||||
totalMessages: 10,
|
||||
}) as T,
|
||||
});
|
||||
|
||||
const result = await tool.execute("projected-replay", { sessionKey: "main", offset: 0 });
|
||||
|
||||
expect(result.details).toMatchObject({
|
||||
offset: 0,
|
||||
nextOffset: 2,
|
||||
hasMore: true,
|
||||
totalMessages: 10,
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps history pagination advancing past an already-returned row", async () => {
|
||||
const tool = createSessionsHistoryTool({
|
||||
config: {},
|
||||
callGateway: async <T = Record<string, unknown>>(): Promise<T> =>
|
||||
({
|
||||
messages: [{ role: "assistant", content: "visible", __openclaw: { seq: 7 } }],
|
||||
offset: 4,
|
||||
nextOffset: 5,
|
||||
hasMore: true,
|
||||
totalMessages: 10,
|
||||
}) as T,
|
||||
});
|
||||
|
||||
const result = await tool.execute("cursor-progress", { sessionKey: "main", offset: 4 });
|
||||
|
||||
expect(result.details).toMatchObject({
|
||||
offset: 4,
|
||||
nextOffset: 5,
|
||||
hasMore: true,
|
||||
totalMessages: 10,
|
||||
});
|
||||
});
|
||||
|
||||
it("honors a scoped incarnation grant through the sandbox visibility clamp", async () => {
|
||||
const requesterSessionKey = "agent:main:clickclack:discussion-proof";
|
||||
const targetSessionKey = "agent:main:main";
|
||||
|
||||
@@ -338,17 +338,15 @@ function resolveSessionsHistoryPaginationMetadata(params: {
|
||||
};
|
||||
}
|
||||
|
||||
// Gateway offsets count newest transcript rows already returned. Recompute
|
||||
// from the oldest surviving seq after this tool's own filter/cap passes.
|
||||
const oldestSeq = params.messages
|
||||
// Respect Gateway replay cursors and this tool's own byte cap while always advancing.
|
||||
const seq = params.messages
|
||||
.map((message) => readHistoryMessageSeq(message))
|
||||
.find((seq): seq is number => typeof seq === "number");
|
||||
.find((value): value is number => typeof value === "number");
|
||||
const gatewayOffset = result?.nextOffset;
|
||||
const nextOffset =
|
||||
oldestSeq !== undefined
|
||||
? Math.max(offset, totalMessages - oldestSeq + 1)
|
||||
: typeof result?.nextOffset === "number"
|
||||
? result.nextOffset
|
||||
: undefined;
|
||||
seq === undefined
|
||||
? gatewayOffset
|
||||
: Math.max(offset + 1, Math.min(gatewayOffset ?? totalMessages, totalMessages - seq + 1));
|
||||
const hasMore =
|
||||
nextOffset !== undefined
|
||||
? nextOffset < totalMessages
|
||||
|
||||
Reference in New Issue
Block a user