Merge branch 'fix/websocket-streaming-issues' of https://github.com/siteboon/claudecodeui into fix/websocket-streaming-issues

This commit is contained in:
Haileyesus
2026-05-08 15:14:39 +03:00
5 changed files with 69 additions and 16 deletions

View File

@@ -414,7 +414,9 @@ export class ClaudeSessionsProvider implements IProviderSessions {
let result: ClaudeHistoryResult; let result: ClaudeHistoryResult;
try { try {
result = await getSessionMessages(sessionId, limit, offset); // Load full history first so `total` reflects frontend-normalized messages,
// not raw JSONL records.
result = await getSessionMessages(sessionId, null, 0);
} catch (error) { } catch (error) {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
console.warn(`[ClaudeProvider] Failed to load session ${sessionId}:`, message); console.warn(`[ClaudeProvider] Failed to load session ${sessionId}:`, message);
@@ -422,8 +424,6 @@ export class ClaudeSessionsProvider implements IProviderSessions {
} }
const rawMessages = Array.isArray(result) ? result : (result.messages || []); const rawMessages = Array.isArray(result) ? result : (result.messages || []);
const total = Array.isArray(result) ? rawMessages.length : (result.total || 0);
const hasMore = Array.isArray(result) ? false : Boolean(result.hasMore);
const toolResultMap = new Map<string, ClaudeToolResult>(); const toolResultMap = new Map<string, ClaudeToolResult>();
for (const raw of rawMessages) { for (const raw of rawMessages) {
@@ -464,12 +464,31 @@ export class ClaudeSessionsProvider implements IProviderSessions {
} }
} }
const totalNormalized = normalized.length;
let total = 0;
for (const msg of normalized) {
if (msg.kind !== 'tool_result') {
total += 1;
}
}
const normalizedOffset = Math.max(0, offset);
const normalizedLimit = limit === null ? null : Math.max(0, limit);
const messages = normalizedLimit === null
? normalized
: normalized.slice(
Math.max(0, totalNormalized - normalizedOffset - normalizedLimit),
Math.max(0, totalNormalized - normalizedOffset),
);
const hasMore = normalizedLimit === null
? false
: Math.max(0, totalNormalized - normalizedOffset - normalizedLimit) > 0;
return { return {
messages: normalized, messages,
total, total,
hasMore, hasMore,
offset, offset: normalizedOffset,
limit, limit: normalizedLimit,
}; };
} }
} }

View File

@@ -520,7 +520,9 @@ export class CodexSessionsProvider implements IProviderSessions {
let result: CodexHistoryResult; let result: CodexHistoryResult;
try { try {
result = await getCodexSessionMessages(sessionId, limit, offset); // Load full history first so `total` reflects frontend-normalized messages,
// not raw JSONL records.
result = await getCodexSessionMessages(sessionId, null, 0);
} catch (error) { } catch (error) {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
console.warn(`[CodexProvider] Failed to load session ${sessionId}:`, message); console.warn(`[CodexProvider] Failed to load session ${sessionId}:`, message);
@@ -528,8 +530,6 @@ export class CodexSessionsProvider implements IProviderSessions {
} }
const rawMessages = Array.isArray(result) ? result : (result.messages || []); const rawMessages = Array.isArray(result) ? result : (result.messages || []);
const total = Array.isArray(result) ? rawMessages.length : (result.total || 0);
const hasMore = Array.isArray(result) ? false : Boolean(result.hasMore);
const tokenUsage = Array.isArray(result) ? undefined : result.tokenUsage; const tokenUsage = Array.isArray(result) ? undefined : result.tokenUsage;
const normalized: NormalizedMessage[] = []; const normalized: NormalizedMessage[] = [];
@@ -552,12 +552,33 @@ export class CodexSessionsProvider implements IProviderSessions {
} }
} }
const totalNormalized = normalized.length;
let total = 0;
for (const msg of normalized) {
if (msg.kind !== 'tool_result') {
total += 1;
}
}
console.log(`[CodexProvider] Loaded ${total} frontend messages (${totalNormalized} normalized) for session "${sessionId}".`);
const normalizedOffset = Math.max(0, offset);
const normalizedLimit = limit === null ? null : Math.max(0, limit);
const messages = normalizedLimit === null
? normalized
: normalized.slice(
Math.max(0, totalNormalized - normalizedOffset - normalizedLimit),
Math.max(0, totalNormalized - normalizedOffset),
);
const hasMore = normalizedLimit === null
? false
: Math.max(0, totalNormalized - normalizedOffset - normalizedLimit) > 0;
return { return {
messages: normalized, messages,
total, total,
hasMore, hasMore,
offset, offset: normalizedOffset,
limit, limit: normalizedLimit,
tokenUsage, tokenUsage,
}; };
} }

View File

@@ -386,7 +386,13 @@ export class CursorSessionsProvider implements IProviderSessions {
try { try {
const blobs = await this.loadCursorBlobs(sessionId, projectPath); const blobs = await this.loadCursorBlobs(sessionId, projectPath);
const allNormalized = this.normalizeCursorBlobs(blobs, sessionId); const allNormalized = this.normalizeCursorBlobs(blobs, sessionId);
const total = allNormalized.length; const totalNormalized = allNormalized.length;
let total = 0;
for (const msg of allNormalized) {
if (msg.kind !== 'tool_result') {
total += 1;
}
}
if (limit !== null) { if (limit !== null) {
const start = offset; const start = offset;
@@ -394,8 +400,8 @@ export class CursorSessionsProvider implements IProviderSessions {
? [] ? []
: allNormalized.slice(start, start + limit); : allNormalized.slice(start, start + limit);
const hasMore = limit === 0 const hasMore = limit === 0
? start < total ? start < totalNormalized
: start + limit < total; : start + limit < totalNormalized;
return { return {
messages: page, messages: page,
total, total,

View File

@@ -528,10 +528,16 @@ export class GeminiSessionsProvider implements IProviderSessions {
const messages = pageLimit === null const messages = pageLimit === null
? normalized.slice(start) ? normalized.slice(start)
: normalized.slice(start, start + pageLimit); : normalized.slice(start, start + pageLimit);
let total = 0;
for (const msg of normalized) {
if (msg.kind !== 'tool_result') {
total += 1;
}
}
return { return {
messages, messages,
total: normalized.length, total,
hasMore: pageLimit === null ? false : start + pageLimit < normalized.length, hasMore: pageLimit === null ? false : start + pageLimit < normalized.length,
offset: start, offset: start,
limit: pageLimit, limit: pageLimit,

View File

@@ -626,6 +626,7 @@ export function useChatSessionState({
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [chatMessages.length, isLoadingSessionMessages, searchTarget]); }, [chatMessages.length, isLoadingSessionMessages, searchTarget]);
console.log("[UseChatSessionState] total and chatMessages: ", totalMessages, chatMessages)
// Token usage fetch for Claude // Token usage fetch for Claude
useEffect(() => { useEffect(() => {
if (!selectedProject || !selectedSession?.id) { if (!selectedProject || !selectedSession?.id) {