修复错误bug

This commit is contained in:
2025-10-13 22:58:21 +08:00
parent 72a51fac24
commit 39be84c15f
3 changed files with 1 additions and 90 deletions

View File

@@ -439,17 +439,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
}); });
// Debug logging // Debug logging
useEffect(() => {
console.log('[ClaudeCodeSession] State update:', {
projectPath,
session,
extractedSessionInfo,
effectiveSession,
messagesCount: messages.length,
isLoading
});
}, [projectPath, session, extractedSessionInfo, effectiveSession, messages.length, isLoading]);
// Load session history if resuming // Load session history if resuming
useEffect(() => { useEffect(() => {
if (session) { if (session) {
@@ -479,7 +468,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
if (tabId && projectPath && !session) { if (tabId && projectPath && !session) {
// Only update for new sessions (not resumed sessions) // Only update for new sessions (not resumed sessions)
// This ensures the path is saved when user selects/enters it // This ensures the path is saved when user selects/enters it
console.log('[ClaudeCodeSession] Syncing projectPath to tab:', { tabId, projectPath });
updateTab(tabId, { updateTab(tabId, {
initialProjectPath: projectPath initialProjectPath: projectPath
}); });
@@ -571,7 +559,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
if (activeSession) { if (activeSession) {
// Session is still active, reconnect to its stream // Session is still active, reconnect to its stream
console.log('[ClaudeCodeSession] Found active session, reconnecting:', session.id);
// IMPORTANT: Set claudeSessionId before reconnecting // IMPORTANT: Set claudeSessionId before reconnecting
setClaudeSessionId(session.id); setClaudeSessionId(session.id);
@@ -588,11 +575,9 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
}; };
const reconnectToSession = async (sessionId: string) => { const reconnectToSession = async (sessionId: string) => {
console.log('[ClaudeCodeSession] Reconnecting to session:', sessionId);
// Prevent duplicate listeners // Prevent duplicate listeners
if (isListeningRef.current) { if (isListeningRef.current) {
console.log('[ClaudeCodeSession] Already listening to session, skipping reconnect');
return; return;
} }
@@ -609,7 +594,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
// Set up session-specific listeners // Set up session-specific listeners
const outputUnlisten = await listen<string>(`claude-output:${sessionId}`, async (event) => { const outputUnlisten = await listen<string>(`claude-output:${sessionId}`, async (event) => {
try { try {
console.log('[ClaudeCodeSession] Received claude-output on reconnect:', event.payload);
if (!isMountedRef.current) return; if (!isMountedRef.current) return;
@@ -632,7 +616,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
}); });
const completeUnlisten = await listen<boolean>(`claude-complete:${sessionId}`, async (event) => { const completeUnlisten = await listen<boolean>(`claude-complete:${sessionId}`, async (event) => {
console.log('[ClaudeCodeSession] Received claude-complete on reconnect:', event.payload);
if (isMountedRef.current) { if (isMountedRef.current) {
setIsLoading(false); setIsLoading(false);
hasActiveSessionRef.current = false; hasActiveSessionRef.current = false;
@@ -668,7 +651,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
}; };
const handleSendPrompt = async (prompt: string, model: "sonnet" | "opus" | "opus-plan") => { const handleSendPrompt = async (prompt: string, model: "sonnet" | "opus" | "opus-plan") => {
console.log('[ClaudeCodeSession] handleSendPrompt called with:', { prompt, model, projectPath, claudeSessionId, effectiveSession });
if (!projectPath) { if (!projectPath) {
setError(t('app.selectProjectFirst')); setError(t('app.selectProjectFirst'));
@@ -718,13 +700,11 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
// generic ones to prevent duplicate handling. // generic ones to prevent duplicate handling.
// -------------------------------------------------------------------- // --------------------------------------------------------------------
console.log('[ClaudeCodeSession] Setting up generic event listeners first');
let currentSessionId: string | null = claudeSessionId || effectiveSession?.id || null; let currentSessionId: string | null = claudeSessionId || effectiveSession?.id || null;
// Helper to attach session-specific listeners **once we are sure** // Helper to attach session-specific listeners **once we are sure**
const attachSessionSpecificListeners = async (sid: string) => { const attachSessionSpecificListeners = async (sid: string) => {
console.log('[ClaudeCodeSession] Attaching session-specific listeners for', sid);
const specificOutputUnlisten = await listen<string>(`claude-output:${sid}`, (evt) => { const specificOutputUnlisten = await listen<string>(`claude-output:${sid}`, (evt) => {
handleStreamMessage(evt.payload); handleStreamMessage(evt.payload);
@@ -736,7 +716,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
}); });
const specificCompleteUnlisten = await listen<boolean>(`claude-complete:${sid}`, (evt) => { const specificCompleteUnlisten = await listen<boolean>(`claude-complete:${sid}`, (evt) => {
console.log('[ClaudeCodeSession] Received claude-complete (scoped):', evt.payload);
processComplete(evt.payload); processComplete(evt.payload);
}); });
@@ -754,7 +733,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
const msg = JSON.parse(event.payload) as ClaudeStreamMessage; const msg = JSON.parse(event.payload) as ClaudeStreamMessage;
if (msg.type === 'system' && msg.subtype === 'init' && msg.session_id) { if (msg.type === 'system' && msg.subtype === 'init' && msg.session_id) {
if (!currentSessionId || currentSessionId !== msg.session_id) { if (!currentSessionId || currentSessionId !== msg.session_id) {
console.log('[ClaudeCodeSession] Detected new session_id from generic listener:', msg.session_id);
currentSessionId = msg.session_id; currentSessionId = msg.session_id;
setClaudeSessionId(msg.session_id); setClaudeSessionId(msg.session_id);
@@ -962,7 +940,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
}); });
const genericCompleteUnlisten = await listen<boolean>('claude-complete', (evt) => { const genericCompleteUnlisten = await listen<boolean>('claude-complete', (evt) => {
console.log('[ClaudeCodeSession] Received claude-complete (generic):', evt.payload);
processComplete(evt.payload); processComplete(evt.payload);
}); });
@@ -1029,12 +1006,10 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
// Execute the appropriate command // Execute the appropriate command
if (effectiveSession && !isFirstPrompt) { if (effectiveSession && !isFirstPrompt) {
console.log('[ClaudeCodeSession] Resuming session:', effectiveSession.id);
trackEvent.sessionResumed(effectiveSession.id); trackEvent.sessionResumed(effectiveSession.id);
trackEvent.modelSelected(model); trackEvent.modelSelected(model);
await api.resumeClaudeCode(projectPath, effectiveSession.id, prompt, model); await api.resumeClaudeCode(projectPath, effectiveSession.id, prompt, model);
} else { } else {
console.log('[ClaudeCodeSession] Starting new session');
setIsFirstPrompt(false); setIsFirstPrompt(false);
trackEvent.sessionCreated(model, 'prompt_input'); trackEvent.sessionCreated(model, 'prompt_input');
trackEvent.modelSelected(model); trackEvent.modelSelected(model);
@@ -1329,7 +1304,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
}; };
const handlePreviewUrlChange = (url: string) => { const handlePreviewUrlChange = (url: string) => {
console.log('[ClaudeCodeSession] Preview URL changed to:', url);
openLayoutPreview(url); openLayoutPreview(url);
}; };
@@ -1338,7 +1312,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
isMountedRef.current = true; isMountedRef.current = true;
return () => { return () => {
console.log('[ClaudeCodeSession] Component unmounting, cleaning up listeners');
isMountedRef.current = false; isMountedRef.current = false;
isListeningRef.current = false; isListeningRef.current = false;

View File

@@ -245,8 +245,6 @@ const FloatingPromptInputInner = (
// Extract image paths from prompt text // Extract image paths from prompt text
const extractImagePaths = (text: string): string[] => { const extractImagePaths = (text: string): string[] => {
console.log('[extractImagePaths] Input text length:', text.length);
// Updated regex to handle both quoted and unquoted paths // Updated regex to handle both quoted and unquoted paths
// Pattern 1: @"path with spaces or data URLs" - quoted paths // Pattern 1: @"path with spaces or data URLs" - quoted paths
// Pattern 2: @path - unquoted paths (continues until @ or end) // Pattern 2: @path - unquoted paths (continues until @ or end)
@@ -257,11 +255,9 @@ const FloatingPromptInputInner = (
// First, extract quoted paths (including data URLs) // First, extract quoted paths (including data URLs)
let matches = Array.from(text.matchAll(quotedRegex)); let matches = Array.from(text.matchAll(quotedRegex));
console.log('[extractImagePaths] Quoted matches:', matches.length);
for (const match of matches) { for (const match of matches) {
const path = match[1]; // No need to trim, quotes preserve exact path const path = match[1]; // No need to trim, quotes preserve exact path
console.log('[extractImagePaths] Processing quoted path:', path.startsWith('data:') ? 'data URL' : path);
// For data URLs, use as-is; for file paths, convert to absolute // For data URLs, use as-is; for file paths, convert to absolute
const fullPath = path.startsWith('data:') const fullPath = path.startsWith('data:')
@@ -278,15 +274,12 @@ const FloatingPromptInputInner = (
// Then extract unquoted paths (typically file paths) // Then extract unquoted paths (typically file paths)
matches = Array.from(textWithoutQuoted.matchAll(unquotedRegex)); matches = Array.from(textWithoutQuoted.matchAll(unquotedRegex));
console.log('[extractImagePaths] Unquoted matches:', matches.length);
for (const match of matches) { for (const match of matches) {
const path = match[1].trim(); const path = match[1].trim();
// Skip if it looks like a data URL fragment (shouldn't happen with proper quoting) // Skip if it looks like a data URL fragment (shouldn't happen with proper quoting)
if (path.includes('data:')) continue; if (path.includes('data:')) continue;
console.log('[extractImagePaths] Processing unquoted path:', path);
// Convert relative path to absolute if needed // Convert relative path to absolute if needed
const fullPath = path.startsWith('/') ? path : (projectPath ? `${projectPath}/${path}` : path); const fullPath = path.startsWith('/') ? path : (projectPath ? `${projectPath}/${path}` : path);
@@ -295,16 +288,12 @@ const FloatingPromptInputInner = (
} }
} }
const uniquePaths = Array.from(pathsSet); return Array.from(pathsSet);
console.log('[extractImagePaths] Final extracted paths (unique):', uniquePaths.length);
return uniquePaths;
}; };
// Update embedded images when prompt changes // Update embedded images when prompt changes
useEffect(() => { useEffect(() => {
console.log('[useEffect] Prompt changed:', prompt);
const imagePaths = extractImagePaths(prompt); const imagePaths = extractImagePaths(prompt);
console.log('[useEffect] Setting embeddedImages to:', imagePaths);
setEmbeddedImages(imagePaths); setEmbeddedImages(imagePaths);
}, [prompt, projectPath]); }, [prompt, projectPath]);
@@ -422,7 +411,6 @@ const FloatingPromptInputInner = (
(newCursorPosition > 1 && /\s/.test(newValue[newCursorPosition - 2])); (newCursorPosition > 1 && /\s/.test(newValue[newCursorPosition - 2]));
if (isStartOfCommand) { if (isStartOfCommand) {
console.log('[FloatingPromptInput] / detected for slash command');
setShowSlashCommandPicker(true); setShowSlashCommandPicker(true);
setSlashCommandQuery(""); setSlashCommandQuery("");
setCursorPosition(newCursorPosition); setCursorPosition(newCursorPosition);
@@ -431,7 +419,6 @@ const FloatingPromptInputInner = (
// Check if @ was just typed // Check if @ was just typed
if (projectPath?.trim() && newValue.length > prompt.length && newValue[newCursorPosition - 1] === '@') { if (projectPath?.trim() && newValue.length > prompt.length && newValue[newCursorPosition - 1] === '@') {
console.log('[FloatingPromptInput] @ detected, projectPath:', projectPath);
setShowFilePicker(true); setShowFilePicker(true);
setFilePickerQuery(""); setFilePickerQuery("");
setCursorPosition(newCursorPosition); setCursorPosition(newCursorPosition);

View File

@@ -54,21 +54,6 @@ export const Terminal: React.FC<TerminalProps> = ({
const rows = Math.max(24, Math.floor(availableHeight / lineHeight)); const rows = Math.max(24, Math.floor(availableHeight / lineHeight));
// 计算实际使用的宽度 // 计算实际使用的宽度
const usedWidth = cols * charWidth;
const unusedWidth = availableWidth - usedWidth;
const percentUsed = ((usedWidth / availableWidth) * 100).toFixed(1);
console.log('[Terminal] Size calculation:', {
containerWidth: rect.width,
availableWidth,
charWidth,
cols,
usedWidth,
unusedWidth,
percentUsed: `${percentUsed}%`,
message: unusedWidth > 10 ? `还有 ${unusedWidth.toFixed(1)}px 未使用` : '宽度使用正常'
});
return { cols, rows }; return { cols, rows };
}, []); }, []);
@@ -87,10 +72,6 @@ export const Terminal: React.FC<TerminalProps> = ({
if (dims.actualCellWidth) actualCharWidth = dims.actualCellWidth; if (dims.actualCellWidth) actualCharWidth = dims.actualCellWidth;
if (dims.actualCellHeight) actualLineHeight = dims.actualCellHeight; if (dims.actualCellHeight) actualLineHeight = dims.actualCellHeight;
console.log('[Terminal] Using actual char dimensions:', {
actualCharWidth,
actualLineHeight
});
} }
} catch (e) { } catch (e) {
// 使用默认值 // 使用默认值
@@ -108,22 +89,8 @@ export const Terminal: React.FC<TerminalProps> = ({
const newRows = Math.max(24, Math.floor(availableHeight / actualLineHeight)); const newRows = Math.max(24, Math.floor(availableHeight / actualLineHeight));
// 计算宽度使用情况 // 计算宽度使用情况
const usedWidth = newCols * actualCharWidth;
const unusedWidth = availableWidth - usedWidth;
const percentUsed = ((usedWidth / availableWidth) * 100).toFixed(1);
// 只有当尺寸真的改变时才调整 // 只有当尺寸真的改变时才调整
if (newCols !== terminalSize.cols || newRows !== terminalSize.rows) { if (newCols !== terminalSize.cols || newRows !== terminalSize.rows) {
console.log('[Terminal] Resizing:', {
from: terminalSize,
to: { cols: newCols, rows: newRows },
containerWidth: rect.width,
availableWidth,
usedWidth,
unusedWidth,
percentUsed: `${percentUsed}%`
});
setTerminalSize({ cols: newCols, rows: newRows }); setTerminalSize({ cols: newCols, rows: newRows });
xtermRef.current.resize(newCols, newRows); xtermRef.current.resize(newCols, newRows);
@@ -163,7 +130,6 @@ export const Terminal: React.FC<TerminalProps> = ({
const initializeTerminal = async () => { const initializeTerminal = async () => {
try { try {
console.log('[Terminal] Initializing...');
isInitializedRef.current = true; isInitializedRef.current = true;
// 先计算初始尺寸 // 先计算初始尺寸
@@ -247,23 +213,11 @@ export const Terminal: React.FC<TerminalProps> = ({
const actualLineHeight = dims.actualCellHeight || dims.scaledCellHeight; const actualLineHeight = dims.actualCellHeight || dims.scaledCellHeight;
if (actualCharWidth && actualLineHeight) { if (actualCharWidth && actualLineHeight) {
console.log('[Terminal] Actual character dimensions:', {
charWidth: actualCharWidth,
lineHeight: actualLineHeight
});
// 使用实际尺寸重新计算 // 使用实际尺寸重新计算
const rect = terminalRef.current.getBoundingClientRect(); const rect = terminalRef.current.getBoundingClientRect();
const availableWidth = rect.width - 2; const availableWidth = rect.width - 2;
const newCols = Math.floor(availableWidth / actualCharWidth); const newCols = Math.floor(availableWidth / actualCharWidth);
console.log('[Terminal] Recalculating with actual dimensions:', {
availableWidth,
actualCharWidth,
newCols,
currentCols: xtermRef.current.cols
});
if (newCols > xtermRef.current.cols) { if (newCols > xtermRef.current.cols) {
xtermRef.current.resize(newCols, xtermRef.current.rows); xtermRef.current.resize(newCols, xtermRef.current.rows);
setTerminalSize({ cols: newCols, rows: xtermRef.current.rows }); setTerminalSize({ cols: newCols, rows: xtermRef.current.rows });
@@ -279,7 +233,6 @@ export const Terminal: React.FC<TerminalProps> = ({
// 如果没有有效的 projectPath,跳过创建终端会话 // 如果没有有效的 projectPath,跳过创建终端会话
if (!projectPath || projectPath.trim() === '') { if (!projectPath || projectPath.trim() === '') {
console.log('[Terminal] Skipping session creation - no project path');
if (xtermRef.current) { if (xtermRef.current) {
xtermRef.current.write('\r\n\x1b[33mNo project directory selected. Please select a project to use the terminal.\x1b[0m\r\n'); xtermRef.current.write('\r\n\x1b[33mNo project directory selected. Please select a project to use the terminal.\x1b[0m\r\n');
} }
@@ -315,8 +268,6 @@ export const Terminal: React.FC<TerminalProps> = ({
} }
}); });
console.log('[Terminal] Initialized with session:', newSessionId);
} catch (error) { } catch (error) {
console.error('[Terminal] Failed to initialize:', error); console.error('[Terminal] Failed to initialize:', error);
if (xtermRef.current && isMounted) { if (xtermRef.current && isMounted) {