Add comprehensive tests for CLI functionality and CodexLens compatibility

- Introduced tests for stale running fallback in CLI watch functionality to ensure proper handling of saved conversations.
- Added compatibility tests for CodexLens CLI to verify index initialization despite compatibility conflicts.
- Implemented tests for Smart Search MCP usage to validate default settings and path handling.
- Created tests for UV Manager to ensure Python preference handling works as expected.
- Added a detailed guide for CCW/Codex commands and skills, covering core commands, execution modes, and templates.
This commit is contained in:
catlog22
2026-03-08 17:30:39 +08:00
parent 4254eeeaa7
commit 9aa07e8d01
32 changed files with 2954 additions and 154 deletions

View File

@@ -18,6 +18,7 @@ import {
import { useCliStreamStore } from '@/stores/cliStreamStore';
import { useActiveCliExecutions } from '@/hooks/useActiveCliExecutions';
import { useCliStreamWebSocket } from '@/hooks/useCliStreamWebSocket';
import { getStaleViewerTabs } from './cliViewerPage.utils';
// ========================================
// Constants
@@ -61,13 +62,13 @@ export function CliViewerPage() {
const layout = useViewerLayout();
const panes = useViewerPanes();
const focusedPaneId = useFocusedPaneId();
const { initializeDefaultLayout, addTab } = useViewerStore();
const { initializeDefaultLayout, addTab, removeTab } = useViewerStore();
// CLI Stream Store hooks
const executions = useCliStreamStore((state) => state.executions);
// Active execution sync from server
useActiveCliExecutions(true);
const { isLoading: isSyncing, isFetching: isRefreshing } = useActiveCliExecutions(true);
// CENTRALIZED WebSocket handler - processes each message only ONCE globally
useCliStreamWebSocket();
@@ -106,6 +107,18 @@ export function CliViewerPage() {
});
}, [executions, panes]);
useEffect(() => {
if (isSyncing || isRefreshing) return;
const staleTabs = getStaleViewerTabs(panes, executions);
if (staleTabs.length === 0) return;
staleTabs.forEach(({ paneId, tabId, executionId }) => {
addedExecutionsRef.current.delete(executionId);
removeTab(paneId, tabId);
});
}, [executions, isRefreshing, isSyncing, panes, removeTab]);
// Initialize layout if empty
useEffect(() => {
const paneCount = countPanes(layout);