feat(chat): add message history pagination with scroll-up loading

Return latest messages by default instead of oldest. Support paginated
loading of older messages when scrolling up via IntersectionObserver,
with scrollHeight compensation to preserve scroll position.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Naiyuan Qing 2026-02-05 18:40:15 +08:00
parent c2b5ada2ef
commit 65c2fea1b6
12 changed files with 232 additions and 28 deletions

View file

@ -3,6 +3,9 @@ import { SessionManager } from "../../../agent/session/session-manager.js";
import { resolveSessionPath } from "../../../agent/session/storage.js";
import { RpcError, type RpcHandler } from "../dispatcher.js";
// Must match DEFAULT_MESSAGES_LIMIT from @multica/sdk/actions/rpc
const DEFAULT_LIMIT = 10;
interface GetAgentMessagesParams {
agentId: string;
offset?: number;
@ -14,7 +17,8 @@ export function createGetAgentMessagesHandler(): RpcHandler {
if (!params || typeof params !== "object") {
throw new RpcError("INVALID_PARAMS", "params must be an object");
}
const { agentId, offset = 0, limit = 50 } = params as GetAgentMessagesParams;
const { agentId, limit = DEFAULT_LIMIT } = params as GetAgentMessagesParams;
let { offset } = params as GetAgentMessagesParams;
if (!agentId) {
throw new RpcError("INVALID_PARAMS", "Missing required param: agentId");
}
@ -27,6 +31,12 @@ export function createGetAgentMessagesHandler(): RpcHandler {
const session = new SessionManager({ sessionId: agentId });
const allMessages = session.loadMessages();
const total = allMessages.length;
// When offset is not provided, return the latest messages
if (offset == null) {
offset = Math.max(0, total - limit);
}
const sliced = allMessages.slice(offset, offset + limit);
return { messages: sliced, total, offset, limit };