fix(cursor-history): align pagination with visible rows

Why:
- Cursor normalization emits internal tool_result items so tool outputs can attach to tool cards.
- The UI does not render tool_result as standalone rows.
- Pagination previously mixed datasets: total excluded tool_result, but page slicing and
  hasMore used the unfiltered collection.
- That mismatch caused offset and limit drift versus what users actually see.
- Tool normalization also renamed ApplyPatch to Edit before input normalization.
- That hid the original tool identity from normalizeCursorToolInput and could drop
  patch-specific shaping.

What changed:
- Added one pagination source of truth: renderableMessages filters out tool_result.
- total, page slicing, and hasMore now all use renderableMessages.
- Unlimited-history responses now return renderableMessages for consistent semantics.
- normalizeCursorToolInput now receives rawToolName first.
- The user-facing rename from ApplyPatch to Edit is still preserved in toolName.

Impact:
- Offset and limit now map to visible Cursor rows.
- hasMore reflects remaining renderable history.
- ApplyPatch payloads keep patch-aware normalization while preserving UI naming.
This commit is contained in:
Haileyesus
2026-05-08 16:03:14 +03:00
parent de25f6d78e
commit 54130e8d14

View File

@@ -386,22 +386,17 @@ export class CursorSessionsProvider implements IProviderSessions {
try {
const blobs = await this.loadCursorBlobs(sessionId, projectPath);
const allNormalized = this.normalizeCursorBlobs(blobs, sessionId);
const totalNormalized = allNormalized.length;
let total = 0;
for (const msg of allNormalized) {
if (msg.kind !== 'tool_result') {
total += 1;
}
}
const renderableMessages = allNormalized.filter((msg) => msg.kind !== 'tool_result');
const total = renderableMessages.length;
if (limit !== null) {
const start = offset;
const page = limit === 0
? []
: allNormalized.slice(start, start + limit);
: renderableMessages.slice(start, start + limit);
const hasMore = limit === 0
? start < totalNormalized
: start + limit < totalNormalized;
? start < total
: start + limit < total;
return {
messages: page,
total,
@@ -412,7 +407,7 @@ export class CursorSessionsProvider implements IProviderSessions {
}
return {
messages: allNormalized,
messages: renderableMessages,
total,
hasMore: false,
offset: 0,
@@ -560,6 +555,7 @@ export class CursorSessionsProvider implements IProviderSessions {
|| normalizeToolId(part.tool_call_id)
|| normalizeToolId(part.id)
|| `tool_${i}_${partIdx}`;
const normalizedToolInput = normalizeCursorToolInput(rawToolName, part.args ?? part.input);
const message = createNormalizedMessage({
id: `${baseId}_${partIdx}`,
sessionId,
@@ -567,7 +563,7 @@ export class CursorSessionsProvider implements IProviderSessions {
provider: PROVIDER,
kind: 'tool_use',
toolName,
toolInput: normalizeCursorToolInput(toolName, part.args ?? part.input),
toolInput: normalizedToolInput,
toolId,
});
messages.push(message);