mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-07 22:05:39 +08:00
Merge branch 'fix/websocket-streaming-issues' of https://github.com/siteboon/claudecodeui into fix/websocket-streaming-issues
This commit is contained in:
@@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user